#include "gb.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

void gb_check_interrupts(gb_state *gb);
// CB prefix opcode's opcode table
int CB_exec(gb_state *gb, int op1);

int gb_cpu_execute(gb_state *gb, int cycles_left)
{
    int opcode, op1, op2;
    int cycles_used;
    // Helper variables for certain opcodes
    int carry, address, temp;

    while(cycles_left > 0)
    {
        opcode = gb_read_mem(gb, gb->PC);
        op1 = gb_read_mem(gb, gb->PC+1);
        op2 = gb_read_mem(gb, gb->PC+2);
        switch(opcode)
        {
            case 0x00:                  // NOP
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x01:                  // LD BC,2byte
                gb->B = op2;
                gb->C = op1;
                gb->PC += 3;
                cycles_used = 12;
                break;
            case 0x02:                  // LD (BC),A
                gb_write_mem(gb,
                    (gb->B << 8) | gb->C,
                    gb->A);
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x03:                  // INC BC
                gb->C++;
                if(!(gb->C & REG_MAX))
                {
                    gb->C = 0;
                    gb->B++;
                    if(!(gb->B & REG_MAX))
                    {
                        gb->B = 0;
                    }
                }
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x04:                  // INC B
                gb->F &= C_FL;
                switch(gb->B)
                {
                    case REG_MAX:
                        gb->B = 0x00;
                        gb->F |= ZERO_FL | HC_FL;
                        break;
                    case HALF_REG:
                        gb->B = 0x10;
                        gb->F |= HC_FL;
                        break;
                    default:
                        gb->B++;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x05:                  // DEC B
                gb->F &= C_FL;
                gb->F |= SUB_FL;
                switch(gb->B)
                {
                    case 0x00:
                        gb->B = 0xff;
                        gb->F |= HC_FL;
						break;
                    case 0x01:
                        gb->B = 0x00;
                        gb->F |= ZERO_FL;
                        break;
                    case 0x10:
                        gb->B = 0x0f;
                        gb->F |= HC_FL;
                        break;
                    default:
                        gb->B--;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x06:                  // LD B,1byte
                gb->B = op1;
                gb->PC += 2;
                cycles_used = 8;
                break;
            case 0x07:                  // RLC A
                gb->F = 0;
                gb->A <<= 1;
                if(gb->A & 0x100)
                {
                    gb->A |= 1;
                    gb->F |= C_FL;
                    gb->A &= REG_MAX;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x08:                  // LD (2byte),SP
                address = (op2 << 8) | op1;
                gb_write_mem(gb,
                    address, gb->SP & REG_MAX);
                gb_write_mem(gb,
                    address+1, (gb->SP >> 8) & REG_MAX);
                gb->PC += 3;
                cycles_used = 20;
                break;
            case 0x09:                  // ADD HL,BC
                gb->F &= ZERO_FL;
                gb->L += gb->C;
                carry = 0;
                if(gb->L & ~REG_MAX)
                {
                    gb->F |= HC_FL;
                    gb->L &= REG_MAX;
                    carry = 1;
                }
                gb->H += gb->B + carry;
                if(gb->H & ~REG_MAX)
                {
                    gb->F |= C_FL;
                    gb->H &= REG_MAX;
                }
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x0a:                  // LD A,(BC)
                gb->A =
                    gb_read_mem(gb,
                    (gb->B << 8) | gb->C);
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x0b:                  // DEC BC
                if(gb->C == 0x00)
                {
                    gb->C = REG_MAX;
                    if(gb->B == 0x00)
                    {
                        gb->B = REG_MAX;
                    }
                    else
                    {
                        gb->B--;
                    }
                }
                else
                {
                    gb->C--;
                }
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x0c:                  // INC C
                gb->F &= C_FL;
                switch(gb->C)
                {
                    case REG_MAX:
                        gb->C = 0x00;
                        gb->F |= ZERO_FL | HC_FL;
                        break;
                    case HALF_REG:
                        gb->C = 0x10;
                        gb->F |= HC_FL;
                        break;
                    default:
                        gb->C++;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x0d:                  // DEC C
                gb->F &= C_FL;
                gb->F |= SUB_FL;
                switch(gb->C)
                {
                    case 0x00:
                        gb->C = 0xff;
                        gb->F |= HC_FL;
						break;
                    case 0x01:
                        gb->C = 0x00;
                        gb->F |= ZERO_FL;
                        break;
                    case 0x10:
                        gb->C = 0x0f;
                        gb->F |= HC_FL;
                        break;
                    default:
                        gb->C--;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x0e:                  // LD C,1byte
                gb->C = op1;
                gb->PC += 2;
                cycles_used = 8;
                break;
            case 0x0f:                  // RRC A
                gb->F = 0;
                if(gb->A & 1)
                {
                    gb->F |= C_FL;
                    gb->A |= 0x100;
                }
                gb->A >>= 1;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x10:                  // STOP
                gb->PC += 2;
                cycles_used = 4;
                break;
            case 0x11:                  // LD DE,2byte
                gb->D = op2;
                gb->E = op1;
                gb->PC += 3;
                cycles_used = 12;
                break;
            case 0x12:                  // LD (DE),A
                gb_write_mem(gb,
                    (gb->D << 8) | gb->E,
                    gb->A);
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x13:                  // INC DE
                gb->E++;
                if(!(gb->E & REG_MAX))
                {
                    gb->E = 0;
                    gb->D++;
                    if(!(gb->D & REG_MAX))
                    {
                        gb->D = 0;
                    }
                }
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x14:                  // INC D
                gb->F &= C_FL;
                switch(gb->D)
                {
                    case REG_MAX:
                        gb->D = 0x00;
                        gb->F |= ZERO_FL | HC_FL;
                        break;
                    case HALF_REG:
                        gb->D = 0x10;
                        gb->F |= HC_FL;
                        break;
                    default:
                        gb->D++;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x15:                  // DEC D
                gb->F &= C_FL;
                gb->F |= SUB_FL;
                switch(gb->D)
                {
                    case 0x00:
                        gb->D = 0xff;
                        gb->F |= HC_FL;
						break;
                    case 0x01:
                        gb->D = 0x00;
                        gb->F |= ZERO_FL;
                        break;
                    case 0x10:
                        gb->D = 0x0f;
                        gb->F |= HC_FL;
                        break;
                    default:
                        gb->D--;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x16:                  // LD D,1byte
                gb->D = op1;
                gb->PC += 2;
                cycles_used = 8;
                break;
            case 0x17:                  // RL A
                gb->A <<= 1;
                if(gb->F & C_FL)
                {
                    gb->A |= 1;
                }
                gb->F = 0;
                if(gb->A & 0x100)
                {
                    gb->F |= C_FL;
                    gb->A &= REG_MAX;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x18:                  // JR 1byte(signed)
                if(op1 & 0x80)
                {
                    gb->PC += (op1 & 0x7f) - 128;
                }
                else
                {
                    gb->PC += op1;
                }
                gb->PC += 2;
                cycles_used = 12;
                break;
            case 0x19:                  // ADD HL,DE
                gb->F &= ZERO_FL;
                gb->L += gb->E;
                carry = 0;
                if(gb->L & ~REG_MAX)
                {
                    gb->F |= HC_FL;
                    gb->L &= REG_MAX;
                    carry = 1;
                }
                gb->H += gb->D + carry;
                if(gb->H & ~REG_MAX)
                {
                    gb->F |= C_FL;
                    gb->H &= REG_MAX;
                }
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x1a:                  // LD A,(DE)
                gb->A =
                    gb_read_mem(gb,
                    (gb->D << 8) | gb->E);
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x1b:                  // DEC DE
                if(gb->E == 0x00)
                {
                    gb->E = REG_MAX;
                    if(gb->D == 0x00)
                    {
                        gb->D = REG_MAX;
                    }
                    else
                    {
                        gb->D--;
                    }
                }
                else
                {
                    gb->E--;
                }
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x1c:                  // INC E
                gb->F &= C_FL;
                switch(gb->E)
                {
                    case REG_MAX:
                        gb->E = 0x00;
                        gb->F |= ZERO_FL | HC_FL;
                        break;
                    case HALF_REG:
                        gb->E = 0x10;
                        gb->F |= HC_FL;
                        break;
                    default:
                        gb->E++;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x1d:                  // DEC E
                gb->F &= C_FL;
                gb->F |= SUB_FL;
                switch(gb->E)
                {
                    case 0x00:
                        gb->E = 0xff;
                        gb->F |= HC_FL;
						break;
                    case 0x01:
                        gb->E = 0x00;
                        gb->F |= ZERO_FL;
                        break;
                    case 0x10:
                        gb->E = 0x0f;
                        gb->F |= HC_FL;
                        break;
                    default:
                        gb->E--;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x1e:                  // LD E,1byte
                gb->E = op1;
                gb->PC += 2;
                cycles_used = 8;
                break;
            case 0x1f:                  // RR A
                if(gb->F & C_FL)
                {
                    gb->A |= 0x100;
                }
                gb->F = 0;
                if(gb->A & 0x01)
                {
                    gb->F |= C_FL;
                }
                gb->A >>= 1;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x20:                  // JR, NZ,1byte(signed)
                if(!(gb->F & ZERO_FL))
                {
                    if(op1 & 0x80)
                    {
                        gb->PC += (op1 & 0x7f) - 128;
                    }
                    else
                    {
                        gb->PC += op1;
                    }
                    cycles_used = 12;
                }
                else
                {
                    cycles_used = 8;
                }
                gb->PC += 2;
                break;
            case 0x21:                  // LD HL,2bytes
                gb->H = op2;
                gb->L = op1;
                gb->PC += 3;
                cycles_used = 12;
                break;
            case 0x22:                  // LD (HL+),A
                gb_write_mem(gb,
                    (gb->H << 8) | gb->L,
                    gb->A);
                gb->L++;
                if(gb->L > REG_MAX)
                {
                    gb->L = 0;
                    gb->H++;
                    if(gb->H > REG_MAX)
                    {
                        gb->H = 0;
                    }
                }
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x23:                  // INC HL
                gb->L++;
                if(gb->L > REG_MAX)
                {
                    gb->L = 0;
                    gb->H++;
                    if(gb->H > REG_MAX)
                    {
                        gb->H = 0;
                    }
                }
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x24:                  // INC H
                gb->F &= C_FL;
                switch(gb->H)
                {
                    case REG_MAX:
                        gb->H = 0x00;
                        gb->F |= ZERO_FL | HC_FL;
                        break;
                    case HALF_REG:
                        gb->H = 0x10;
                        gb->F |= HC_FL;
                        break;
                    default:
                        gb->H++;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x25:                  // DEC H
                gb->F &= C_FL;
                gb->F |= SUB_FL;
                switch(gb->H)
                {
                    case 0x00:
                        gb->H = 0xff;
                        gb->F |= HC_FL;
						break;
                    case 0x01:
                        gb->H = 0x00;
                        gb->F |= ZERO_FL;
                        break;
                    case 0x10:
                        gb->H = 0x0f;
                        gb->F |= HC_FL;
                        break;
                    default:
                        gb->H--;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x26:                  // LD H,1byte
                gb->H = op1;
                gb->PC += 2;
                cycles_used = 8;
                break;
            case 0x27:                  // DAA
                temp = 0;
                if(gb->A > 0x99 ||
                        gb->F & C_FL)
                {
                    temp |= 0x60;
                }
                if((gb->A & HALF_REG) > 0x09 ||
                        gb->F & HC_FL)
                {
                    temp |= 0x06;
                }
                if(gb->F & SUB_FL)
                {
                    gb->A -= temp;
                }
                else
                {
                    gb->A += temp;
                }
                gb->F &= SUB_FL;
                if(temp & 0x60)
                {
                    gb->F |= C_FL;
                }
                if(temp & 0x06)
                {
                    gb->F |= HC_FL;
                }
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->A &= REG_MAX;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x28:                  // JR Z,1byte(signed)
                if(gb->F & ZERO_FL)
                {
                    if(op1 & 0x80)
                    {
                        gb->PC += (op1 & 0x7f) - 128;
                    }
                    else
                    {
                        gb->PC += op1;
                    }
                    cycles_used = 12;
                }
                else
                {
                    cycles_used = 8;
                }
                gb->PC += 2;
                break;
            case 0x29:                  // ADD HL,HL
                gb->F &= ZERO_FL;
                gb->L <<= 1;
                carry = 0;
                if(gb->L & 0x100)
                {
                    gb->F |= HC_FL;
                    carry = 1;
                    gb->L &= REG_MAX;
                }
                gb->H = (gb->H << 1) | carry;
                if(gb->H & 0x100)
                {
                    gb->F |= C_FL;
                    gb->H &= REG_MAX;
                }
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x2a:                  // LD A,(HL+)
                gb->A =
                    gb_read_mem(gb, (gb->H << 8) | gb->L);
				if(gb->L == REG_MAX)
				{
					gb->L = 0;
					gb->H++;
					gb->H &= REG_MAX;
				}
				else
				{
					gb->L++;
				}
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x2b:                  // DEC HL
                if(gb->L == 0x00)
                {
                    gb->L = REG_MAX;
                    if(gb->H == 0x00)
                    {
                        gb->H = REG_MAX;
                    }
                    else
                    {
                        gb->H--;
                    }
                }
                else
                {
                    gb->L--;
                }
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x2c:                  // INC L
                gb->F &= C_FL;
                switch(gb->L)
                {
                    case REG_MAX:
                        gb->L = 0x00;
                        gb->F |= ZERO_FL | HC_FL;
                        break;
                    case HALF_REG:
                        gb->L = 0x10;
                        gb->F |= HC_FL;
                        break;
                    default:
                        gb->L++;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x2d:                  // DEC L
                gb->F &= C_FL;
                gb->F |= SUB_FL;
                switch(gb->L)
                {
                    case 0x00:
                        gb->L = 0xff;
                        gb->F |= HC_FL;
						break;
                    case 0x01:
                        gb->L = 0x00;
                        gb->F |= ZERO_FL;
                        break;
                    case 0x10:
                        gb->L = 0x0f;
                        gb->F |= HC_FL;
                        break;
                    default:
                        gb->L--;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x2e:                  // LD L,1byte
                gb->L = op1;
                gb->PC += 2;
                cycles_used = 8;
                break;
            case 0x2f:                  // CPL
                gb->F |= SUB_FL | HC_FL;
                gb->A ^= REG_MAX;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x30:                  // JR NC,1byte
                if(!(gb->F & C_FL))
                {
                    if(op1 & 0x80)
                    {
                        gb->PC += (op1 & 0x7f) - 128;
                    }
                    else
                    {
                        gb->PC += op1;
                    }
                    cycles_used = 12;
                }
                else
                {
                    cycles_used = 8;
                }
                gb->PC += 2;
                break;
            case 0x31:                  // LD SP,2bytes
                gb->SP = (op2 << 8) | op1;
                gb->PC += 3;
                cycles_used = 12;
                break;
            case 0x32:                  // LD (HL-),A
                gb_write_mem(gb,
                    (gb->H << 8) | gb->L,
                    gb->A);
                if(gb->L == 0x00)
                {
                    gb->L = REG_MAX;
                    if(gb->H == 0x00)
                    {
                        gb->H = REG_MAX;
                    }
                    else
                    {
                        gb->H--;
                    }
                }
                else
                {
                    gb->L--;
                }
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x33:                  // INC SP
                gb->SP++;
                gb->SP &= DOUBLE_REG;
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x34:                  // INC (HL)
                address = (gb->H << 8) | gb->L;
                temp = gb_read_mem(gb, address);
                gb->F &= C_FL;
                switch(temp)
                {
                    case REG_MAX:
                        temp = 0x00;
                        gb->F |= ZERO_FL | HC_FL;
                        break;
                    case HALF_REG:
                        temp = 0x10;
                        gb->F |= HC_FL;
                        break;
                    default:
                        temp++;
                }
                gb_write_mem(gb, address, temp);
                gb->PC += 1;
                cycles_used = 12;
                break;
            case 0x35:                  // DEC (HL)
                address = (gb->H << 8) | gb->L;
                temp = gb_read_mem(gb, address);
                gb->F &= C_FL;
                gb->F |= SUB_FL;
                switch(temp)
                {
                    case 0x00:
                        temp = 0xff;
                        gb->F |= HC_FL;
						break;
                    case 0x01:
                        temp = 0x00;
                        gb->F |= ZERO_FL;
                        break;
                    case 0x10:
                        temp = 0x0f;
                        gb->F |= HC_FL;
                        break;
                    default:
                        temp--;
                }
                gb_write_mem(gb, address, temp);
                gb->PC += 1;
                cycles_used = 12;
                break;
            case 0x36:                  // LD (HL),ibyte
                address = (gb->H << 8) | gb->L;
                gb_write_mem(gb, address, op1);
                gb->PC += 2;
                cycles_used = 12;
                break;
            case 0x37:                  // SCF (set carry flag)
                gb->F &= ZERO_FL;
                gb->F |= C_FL;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x38:                  // JR C,1byte(signed)
                if(gb->F & C_FL)
                {
                    if(op1 & 0x80)
                    {
                        gb->PC += (op1 & 0x7f) - 128;
                    }
                    else
                    {
                        gb->PC += op1;
                    }
                    cycles_used = 12;
                }
                else
                {
                    cycles_used = 8;
                }
                gb->PC += 2;
                break;
            case 0x39:                  // ADD HL,SP
                gb->F &= ZERO_FL;
                gb->L += gb->SP & REG_MAX;
                carry = 0;
                if(gb->L > REG_MAX)
                {
                    gb->F |= HC_FL;
                    gb->L &= REG_MAX;
                    carry = 1;
                }
                gb->H += (gb->SP >> 8) + carry;
                if(gb->H > REG_MAX)
                {
                    gb->F |= C_FL;
                    gb->H &= REG_MAX;
                }
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x3a:                  // LD A,(HL-)
                gb->A =
                    gb_read_mem(gb,
                        (gb->H << 8) | gb->L);
                if(gb->L == 0x00)
                {
                    gb->L = REG_MAX;
                    if(gb->H == 0x00)
                    {
                        gb->H = REG_MAX;
                    }
                    else
                    {
                        gb->H--;
                    }
                }
                else
                {
                    gb->L--;
                }
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x3b:                  // DEC SP
                gb->SP--;
                gb->SP &= DOUBLE_REG;
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x3c:                  // INC A
                gb->F &= C_FL;
                switch(gb->A)
                {
                    case REG_MAX:
                        gb->A = 0x00;
                        gb->F |= ZERO_FL | HC_FL;
                        break;
                    case HALF_REG:
                        gb->A = 0x10;
                        gb->F |= HC_FL;
                        break;
                    default:
                        gb->A++;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x3d:                  // DEC A
                gb->F &= C_FL;
                gb->F |= SUB_FL;
                switch(gb->A)
                {
                    case 0x00:
                        gb->A = 0xff;
                        gb->F |= HC_FL;
                        break;
                    case 0x01:
                        gb->A = 0x00;
                        gb->F |= ZERO_FL;
                        break;
                    case 0x10:
                        gb->A = 0x0f;
                        gb->F |= HC_FL;
                        break;
                    default:
                        gb->A--;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x3e:                  // LD A,1byte
                gb->A = op1;
                gb->PC += 2;
                cycles_used = 8;
                break;
            case 0x3f:                  // CCF (complement carry flag)
                gb->F &= (ZERO_FL | C_FL);
                gb->F ^= C_FL;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x40:                  // LD B,B
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x41:                  // LD B,C
                gb->B = gb->C;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x42:                  // LD B,D
                gb->B = gb->D;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x43:                  // LD B,E
                gb->B = gb->E;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x44:                  // LD B,H
                gb->B = gb->H;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x45:                  // LD B,L
                gb->B = gb->L;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x46:                  // LD B,(HL)
                temp = gb_read_mem(gb,
                    (gb->H << 8) | gb->L);
                gb->B = temp;
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x47:                  // LD B,A
                gb->B = gb->A;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x48:                  // LD C,B
                gb->C = gb->B;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x49:                  // LD C,C
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x4a:                  // LD C,D
                gb->C = gb->D;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x4b:                  // LD C,E
                gb->C = gb->E;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x4c:                  // LD C,H
                gb->C = gb->H;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x4d:                  // LD C,L
                gb->C = gb->L;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x4e:                  // LD C,(HL)
                temp = gb_read_mem(gb,
                    (gb->H << 8) | gb->L);
                gb->C = temp;
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x4f:                  // LD C,A
                gb->C = gb->A;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x50:                  // LD D,B
                gb->D = gb->B;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x51:                  // LD D,C
                gb->D = gb->C;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x52:                  // LD D,D
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x53:                  // LD D,E
                gb->D = gb->E;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x54:                  // LD D,H
                gb->D = gb->H;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x55:                  // LD D,L
                gb->D = gb->L;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x56:                  // LD D,(HL)
                temp = gb_read_mem(gb,
                    (gb->H << 8) | gb->L);
                gb->D = temp;
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x57:                  // LD D,A
                gb->D = gb->A;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x58:                  // LD E,B
                gb->E = gb->B;
                gb->PC += 1;
                cycles_used = 4;
                break;
			case 0x59:					// LD E,C
				gb->E = gb->C;
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0x5a:                  // LD E,D
                gb->E = gb->D;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x5b:                  // LD E,E
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x5c:                  // LD E,H
                gb->E = gb->H;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x5d:                  // LD E,L
				gb->E = gb->L;
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0x5e:                  // LD E,(HL)
                temp = gb_read_mem(gb,
                    (gb->H << 8) | gb->L);
                gb->E = temp;
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x5f:                  // LD E,A
				gb->E = gb->A;
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0x60:                  // LD H,B
				gb->H = gb->B;
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0x61:                  // LD H,C
                gb->H = gb->C;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x62:                  // LD H,D
				gb->H = gb->D;
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0x63:                  // LD H,E
				gb->H = gb->E;
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0x64:                  // LD H,H
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x65:                  // LD H,L
				gb->H = gb->L;
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0x66:                  // LD H,(HL)
                temp = gb_read_mem(gb,
                    (gb->H << 8) | gb->L);
                gb->H = temp;
                gb->PC += 1;
                cycles_used = 8;
                break;
			case 0x67:					// LD H,A
				gb->H = gb->A;
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0x68:                  // LD L,B
                gb->L = gb->B;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x69:                  // LD L,C
                gb->L = gb->C;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x6a:                  // LD L,D
                gb->L = gb->D;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x6b:                  // LD L,E
				gb->L = gb->E;
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0x6c:                  // LD L,H
                gb->L = gb->H;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x6d:                  // LD L,L
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x6e:                  // LD L,(HL)
                temp = gb_read_mem(gb,
                        (gb->H << 8) | gb->L);
                gb->L = temp;
                gb->PC += 1;
                cycles_used = 8;
                break;
			case 0x6f:					// LD L,A
				gb->L = gb->A;
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0x70:                  // LD (HL),B
                address = (gb->H << 8) | gb->L;
                gb_write_mem(gb, address, gb->B);
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x71:                  // LD (HL),C
                address = (gb->H << 8) | gb->L;
                gb_write_mem(gb, address, gb->C);
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x72:                  // LD (HL),D
                address = (gb->H << 8) | gb->L;
                gb_write_mem(gb, address, gb->D);
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x73:                  // LD (HL),E
                address = (gb->H << 8) | gb->L;
                gb_write_mem(gb, address, gb->E);
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x74:                  // LD (HL),H
                address = (gb->H << 8) | gb->L;
                gb_write_mem(gb, address, gb->H);
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x75:                  // LD (HL),L
                address = (gb->H << 8) | gb->L;
                gb_write_mem(gb, address, gb->L);
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0x76:                  // HALT until interrupt occurs
                if(gb->IME && (gb->IE & gb->IF & 0x1f))
                    gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x77:                  // LD (HL),A
				address = (gb->H << 8) | gb->L;
                gb_write_mem(gb, address, gb->A);
                gb->PC += 1;
                cycles_used = 8;
                break;
			case 0x78:					// LD A,B
				gb->A = gb->B;
				gb->PC += 1;
				cycles_used = 4;
				break;
			case 0x79:					// LD A,C
				gb->A = gb->C;
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0x7a:                  // LD A,D
                gb->A = gb->D;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x7b:                  // LD A,E
                gb->A = gb->E;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x7c:                  // LD A,H
                gb->A = gb->H;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x7d:                  // LD A,L
                gb->A = gb->L;
                gb->PC += 1;
                cycles_used = 4;
                break;
			case 0x7e:					// LD A,(HL)
				address = (gb->H << 8) | gb->L;
				gb->A = gb_read_mem(gb, address);
				gb->PC += 1;
				cycles_used = 8;
				break;
            case 0x7f:                  // LD A,A
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x80:                  // ADD A,B
                gb->F = 0;
                if(((gb->A & HALF_REG) +
                        (gb->B & HALF_REG)) >
                                HALF_REG)
                {
                    gb->F |= HC_FL;
                }
                gb->A += gb->B;
                if(gb->A > REG_MAX)
                {
                    gb->F |= C_FL;
                    gb->A &= REG_MAX;
                }
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x81:                  // ADD A,C
                gb->F = 0;
                if(((gb->A & HALF_REG) +
                        (gb->C & HALF_REG)) >
                                HALF_REG)
                {
                    gb->F |= HC_FL;
                }
                gb->A += gb->C;
                if(gb->A > REG_MAX)
                {
                    gb->F |= C_FL;
                    gb->A &= REG_MAX;
                }
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x82:                  // ADD A,D
                gb->F = 0;
                if(((gb->A & HALF_REG) +
                        (gb->D & HALF_REG)) >
                                HALF_REG)
                {
                    gb->F |= HC_FL;
                }
                gb->A += gb->D;
                if(gb->A > REG_MAX)
                {
                    gb->F |= C_FL;
                    gb->A &= REG_MAX;
                }
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x83:                  // ADD A,E
                gb->F = 0;
                if(((gb->A & HALF_REG) +
                        (gb->E & HALF_REG)) >
                                HALF_REG)
                {
                    gb->F |= HC_FL;
                }
                gb->A += gb->E;
                if(gb->A > REG_MAX)
                {
                    gb->F |= C_FL;
                    gb->A &= REG_MAX;
                }
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x84:                  // ADD A,H
                gb->F = 0;
                if(((gb->A & HALF_REG) +
                        (gb->H & HALF_REG)) >
                                HALF_REG)
                {
                    gb->F |= HC_FL;
                }
                gb->A += gb->H;
                if(gb->A > REG_MAX)
                {
                    gb->F |= C_FL;
                    gb->A &= REG_MAX;
                }
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x85:                  // ADD A,L
                gb->F = 0;
                if(((gb->A & HALF_REG) +
                        (gb->L & HALF_REG)) >
                                HALF_REG)
                {
                    gb->F |= HC_FL;
                }
                gb->A += gb->L;
                if(gb->A > REG_MAX)
                {
                    gb->F |= C_FL;
                    gb->A &= REG_MAX;
                }
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x86:                  // ADD A,(HL)
                gb->F = 0;
                temp = gb_read_mem(gb,
                        (gb->H << 8) | gb->L);
                if(((gb->A & HALF_REG) +
                        (temp & HALF_REG)) >
                                HALF_REG)
                {
                    gb->F |= HC_FL;
                }
                gb->A += temp;
                if(gb->A > REG_MAX)
                {
                    gb->F |= C_FL;
                    gb->A &= REG_MAX;
                }
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x87:                  // ADD A,A
                gb->F = 0;
                if(((gb->A << 1) & HALF_REG) >
                        HALF_REG)
                {
                    gb->F |= HC_FL;
                }
                gb->A <<= 1;
                if(gb->A > REG_MAX)
                {
                    gb->F |= C_FL;
                    gb->A &= REG_MAX;
                }
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x88:                  // ADC A,B
                carry = 0;
                if(gb->F & C_FL)
                {
                    carry = 1;
                }
                gb->F = 0;
                temp = gb->B + carry;
                if(((gb->A & HALF_REG) +
                        (temp & HALF_REG)) >
                                HALF_REG)
                {
                    gb->F |= HC_FL;
                }
                gb->A += temp;
                if(gb->A > REG_MAX)
                {
                    gb->F |= C_FL;
                    gb->A &= REG_MAX;
                }
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x89:                  // ADC A,C
                carry = 0;
                if(gb->F & C_FL)
                {
                    carry = 1;
                }
                gb->F = 0;
                temp = gb->C + carry;
                if(((gb->A & HALF_REG) +
                        (temp & HALF_REG)) >
                                HALF_REG)
                {
                    gb->F |= HC_FL;
                }
                gb->A += temp;
                if(gb->A > REG_MAX)
                {
                    gb->F |= C_FL;
                    gb->A &= REG_MAX;
                }
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x8a:                  // ADC A,D
                carry = 0;
                if(gb->F & C_FL)
                {
                    carry = 1;
                }
                gb->F = 0;
                temp = gb->D + carry;
                if(((gb->A & HALF_REG) +
                        (temp & HALF_REG)) >
                                HALF_REG)
                {
                    gb->F |= HC_FL;
                }
                gb->A += temp;
                if(gb->A > REG_MAX)
                {
                    gb->F |= C_FL;
                    gb->A &= REG_MAX;
                }
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x8b:                  // ADC A,E
                carry = 0;
                if(gb->F & C_FL)
                {
                    carry = 1;
                }
                gb->F = 0;
                temp = gb->E + carry;
                if(((gb->A & HALF_REG) +
                        (temp & HALF_REG)) >
                                HALF_REG)
                {
                    gb->F |= HC_FL;
                }
                gb->A += temp;
                if(gb->A > REG_MAX)
                {
                    gb->F |= C_FL;
                    gb->A &= REG_MAX;
                }
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x8c:                  // ADC A,H
                carry = 0;
                if(gb->F & C_FL)
                {
                    carry = 1;
                }
                gb->F = 0;
                temp = gb->H + carry;
                if(((gb->A & HALF_REG) +
                        (temp & HALF_REG)) >
                                HALF_REG)
                {
                    gb->F |= HC_FL;
                }
                gb->A += temp;
                if(gb->A > REG_MAX)
                {
                    gb->F |= C_FL;
                    gb->A &= REG_MAX;
                }
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x8d:                  // ADC A,L
                carry = 0;
                if(gb->F & C_FL)
                {
                    carry = 1;
                }
                gb->F = 0;
                temp = gb->L + carry;
                if(((gb->A & HALF_REG) +
                        (temp & HALF_REG)) >
                                HALF_REG)
                {
                    gb->F |= HC_FL;
                }
                gb->A += temp;
                if(gb->A > REG_MAX)
                {
                    gb->F |= C_FL;
                    gb->A &= REG_MAX;
                }
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
			case 0x8e:					// ADC A,(HL)
				carry = 0;
                if(gb->F & C_FL)
                {
                    carry = 1;
                }
                gb->F = 0;
                temp = gb_read_mem(gb, (gb->H << 8) | gb->L);
				temp += carry;
                if(((gb->A & HALF_REG) +
						(temp & HALF_REG)) >
							HALF_REG)
                {
                    gb->F |= HC_FL;
                }
                gb->A += temp;
                if(gb->A > REG_MAX)
                {
                    gb->F |= C_FL;
                    gb->A &= REG_MAX;
                }
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x8f:                  // ADC A,A
                carry = (gb->F & C_FL) >> C_FL_BIT;
                gb->F = 0;
                if(gb->A & 0x08)
                {
                    gb->F |= HC_FL;
                }
                gb->A <<= 1;
                gb->A |= carry;
                if(gb->A & 0x100)
                {
                    gb->F |= C_FL;
                    gb->A &= REG_MAX;
                }
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
			case 0x90:					// SUB B
				gb->F = SUB_FL;
				if((gb->A & HALF_REG) < (gb->B & HALF_REG))
				{
					gb->F |= HC_FL;
				}
				if(gb->A <= gb->B)
				{
					if(gb->A == gb->B)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
				gb->A -= gb->B;
                gb->A &= REG_MAX;
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0x91:                  // SUB C
				gb->F = SUB_FL;
				if((gb->A & HALF_REG) < (gb->C & HALF_REG))
				{
					gb->F |= HC_FL;
				}
				if(gb->A <= gb->C)
				{
					if(gb->A == gb->C)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
				gb->A -= gb->C;
                gb->A &= REG_MAX;
				gb->PC += 1;
				cycles_used = 4;
				break;
			case 0x92:					// SUB D
				gb->F = SUB_FL;
				if((gb->A & HALF_REG) < (gb->D & HALF_REG))
				{
					gb->F |= HC_FL;
				}
				if(gb->A <= gb->D)
				{
					if(gb->A == gb->D)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
				gb->A -= gb->D;
                gb->A &= REG_MAX;
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0x93:                  // SUB E
				gb->F = SUB_FL;
				if((gb->A & HALF_REG) < (gb->E & HALF_REG))
				{
					gb->F |= HC_FL;
				}
				if(gb->A <= gb->E)
				{
					if(gb->A == gb->E)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
				gb->A -= gb->E;
                gb->A &= REG_MAX;
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0x94:                  // SUB H
				gb->F = SUB_FL;
				if((gb->A & HALF_REG) < (gb->H & HALF_REG))
				{
					gb->F |= HC_FL;
				}
				if(gb->A <= gb->H)
				{
					if(gb->A == gb->H)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
				gb->A -= gb->H;
                gb->A &= REG_MAX;
				gb->PC += 1;
				cycles_used = 4;
				break;
			case 0x95:					// SUB L
				gb->F = SUB_FL;
				if((gb->A & HALF_REG) < (gb->L & HALF_REG))
				{
					gb->F |= HC_FL;
				}
				if(gb->A <= gb->L)
				{
					if(gb->A == gb->L)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
				gb->A -= gb->L;
                gb->A &= REG_MAX;
				gb->PC += 1;
				cycles_used = 4;
				break;
			case 0x96:					// SUB (HL)
				gb->F = SUB_FL;
				temp = gb_read_mem(gb, (gb->H << 8) | gb->L);
				if((gb->A & HALF_REG) < (temp & HALF_REG))
				{
					gb->F |= HC_FL;
				}
				if(gb->A <= temp)
				{
					if(gb->A == temp)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
				gb->A -= temp;
                gb->A &= REG_MAX;
				gb->PC += 1;
				cycles_used = 8;
				break;
			case 0x97:					// SUB A
				gb->F = ZERO_FL | SUB_FL;
				gb->A = 0;
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0x98:                  // SBC A,B
                carry = (gb->F & C_FL) >> C_FL_BIT;
                gb->F = SUB_FL;
                temp = gb->B + carry;
                if((gb->A & HALF_REG) < (temp & HALF_REG))
                {
                    gb->F |= HC_FL;
                }
				if(gb->A <= temp)
				{
					if(gb->A == temp)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
                gb->A -= temp;
				gb->A &= REG_MAX;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x9a:                  // SBC A,D
                carry = (gb->F & C_FL) >> C_FL_BIT;
                gb->F = SUB_FL;
                temp = gb->D + carry;
                if((gb->A & HALF_REG) < (temp & HALF_REG))
                {
                    gb->F |= HC_FL;
                }
				if(gb->A <= temp)
				{
					if(gb->A == temp)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
                gb->A -= temp;
				gb->A &= REG_MAX;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x9b:                  // SBC A,E
                carry = (gb->F & C_FL) >> C_FL_BIT;
                gb->F = SUB_FL;
                temp = gb->E + carry;
                if((gb->A & HALF_REG) < (temp & HALF_REG))
                {
                    gb->F |= HC_FL;
                }
				if(gb->A <= temp)
				{
					if(gb->A == temp)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
                gb->A -= temp;
				gb->A &= REG_MAX;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x9c:                  // SBC A,H
				carry = (gb->F & C_FL) >> C_FL_BIT;
                gb->F = SUB_FL;
                temp = gb->H + carry;
                if((gb->A & HALF_REG) < (temp & HALF_REG))
                {
                    gb->F |= HC_FL;
                }
				if(gb->A <= temp)
				{
					if(gb->A == temp)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
                gb->A -= temp;
				gb->A &= REG_MAX;
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0x9d:                  // SBC A,L
                carry = (gb->F & C_FL) >> C_FL_BIT;
                gb->F = SUB_FL;
                temp = gb->L + carry;
                if((gb->A & HALF_REG) < (temp & HALF_REG))
                {
                    gb->F |= HC_FL;
                }
				if(gb->A <= temp)
				{
					if(gb->A == temp)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
                gb->A -= temp;
				gb->A &= REG_MAX;
                gb->PC += 1;
                cycles_used = 4;
                break;
			case 0x9e:					// SBC A,(HL)
				carry = (gb->F & C_FL) >> C_FL_BIT;
                gb->F = SUB_FL;
                temp = gb_read_mem(gb, (gb->H << 8) | gb->L) + carry;
                if((gb->A & HALF_REG) < (temp & HALF_REG))
                {
                    gb->F |= HC_FL;
                }
				if(gb->A <= temp)
				{
					if(gb->A == temp)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
                gb->A -= temp;
				gb->A &= REG_MAX;
                gb->PC += 1;
                cycles_used = 4;
                break;
			case 0x9f:					// SBC A,A
				gb->A = 0;
				if(gb->F & C_FL)
				{
					gb->A = REG_MAX;
					gb->F = HC_FL | C_FL | SUB_FL;
				}
				else
				{
					gb->F = ZERO_FL | SUB_FL;
				}
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0xa0:                  // AND B
                gb->F = HC_FL;
                gb->A &= gb->B;
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0xa1:                  // AND C
                gb->F = HC_FL;
                gb->A &= gb->C;
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0xa2:                  // AND D
                gb->F = HC_FL;
                gb->A &= gb->D;
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0xa3:                  // AND E
                gb->F = HC_FL;
                gb->A &= gb->E;
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0xa4:                  // AND H
                gb->F = HC_FL;
                gb->A &= gb->H;
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0xa5:                  // AND L
                gb->F = HC_FL;
                gb->A &= gb->L;
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0xa6:                  // AND (HL)
                gb->F = HC_FL;
                temp = gb_read_mem(gb,
                        (gb->H << 8) | gb->L);
                gb->A &= temp;
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0xa7:                  // AND A
                gb->F = HC_FL;
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0xa8:                  // XOR B
                gb->F = 0;
                gb->A ^= gb->B;
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0xa9:                  // XOR C
                gb->F = 0;
                gb->A ^= gb->C;
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0xaa:                  // XOR D
                gb->F = 0;
                gb->A ^= gb->D;
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0xab:                  // XOR E
                gb->F = 0;
                gb->A ^= gb->E;
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0xac:                  // XOR H
                gb->F = 0;
                gb->A ^= gb->H;
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0xad:                  // XOR L
                gb->F = 0;
                gb->A ^= gb->L;
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
            case 0xae:                  // XOR (HL)
                gb->F = 0;
                temp = gb_read_mem(gb,
                        (gb->H << 8) | gb->L);
                gb->A ^= temp;
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0xaf:                  // XOR A
                gb->A = 0;
                gb->F = ZERO_FL;
                gb->PC += 1;
                cycles_used = 4;
                break;
			case 0xb0:					// OR B
				gb->F = 0;
				gb->A |= gb->B;
				if(gb->A == 0x00)
				{
					gb->F |= ZERO_FL;
				}
				gb->PC += 1;
				cycles_used = 4;
				break;
			case 0xb1:					// OR C
				gb->F = 0;
				gb->A |= gb->C;
				if(gb->A == 0x00)
				{
					gb->F |= ZERO_FL;
				}
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0xb2:                  // OR D
				gb->F = 0;
				gb->A |= gb->D;
				if(gb->A == 0x00)
				{
					gb->F |= ZERO_FL;
				}
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0xb3:                  // OR E
				gb->F = 0;
				gb->A |= gb->E;
				if(gb->A == 0x00)
				{
					gb->F |= ZERO_FL;
				}
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0xb4:                  // OR H
				gb->F = 0;
				gb->A |= gb->H;
				if(gb->A == 0x00)
				{
					gb->F |= ZERO_FL;
				}
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0xb5:                  // OR L
				gb->F = 0;
				gb->A |= gb->L;
				if(gb->A == 0x00)
				{
					gb->F |= ZERO_FL;
				}
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0xb6:                  // OR (HL)
                gb->F = 0;
                temp = gb_read_mem(gb,
                        (gb->H << 8) | gb->L);
                gb->A |= temp;
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0xb7:                  // OR A
                gb->F = 0;
                if(gb->A == 0x00)
                {
                    gb->F = ZERO_FL;
                }
                gb->PC += 1;
                cycles_used = 4;
                break;
			case 0xb8:					// CP B
				gb->F = SUB_FL;
				if((gb->A & HALF_REG) < (gb->B & HALF_REG))
				{
					gb->F |= HC_FL;
				}
				if(gb->A <= gb->B)
				{
					if(gb->A == gb->B)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
				gb->PC += 1;
				cycles_used = 4;
				break;
			case 0xb9:					// CP C
				gb->F = SUB_FL;
				if((gb->A & HALF_REG) < (gb->C & HALF_REG))
				{
					gb->F |= HC_FL;
				}
				if(gb->A <= gb->C)
				{
					if(gb->A == gb->C)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0xba:                  // CP D
                gb->F = SUB_FL;
				if((gb->A & HALF_REG) < (gb->D & HALF_REG))
				{
					gb->F |= HC_FL;
				}
				if(gb->A <= gb->D)
				{
					if(gb->A == gb->D)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0xbb:                  // CP E
                gb->F = SUB_FL;
				if((gb->A & HALF_REG) < (gb->E & HALF_REG))
				{
					gb->F |= HC_FL;
				}
				if(gb->A <= gb->E)
				{
					if(gb->A == gb->E)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0xbc:                  // CP H
                gb->F = SUB_FL;
				if((gb->A & HALF_REG) < (gb->H & HALF_REG))
				{
					gb->F |= HC_FL;
				}
				if(gb->A <= gb->H)
				{
					if(gb->A == gb->H)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0xbd:                  // CP L
                gb->F = SUB_FL;
				if((gb->A & HALF_REG) < (gb->L & HALF_REG))
				{
					gb->F |= HC_FL;
				}
				if(gb->A <= gb->L)
				{
					if(gb->A == gb->L)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
				gb->PC += 1;
				cycles_used = 4;
				break;
			case 0xbe:					// CP (HL)
				gb->F = SUB_FL;
				temp = gb_read_mem(gb, (gb->H << 8) | gb->L);
				if((gb->A & HALF_REG) < (temp & HALF_REG))
				{
					gb->F |= HC_FL;
				}
				if(gb->A <= temp)
				{
					if(gb->A == temp)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
				gb->PC += 1;
				cycles_used = 8;
				break;
			case 0xbf:					// CP A
				gb->F = SUB_FL;
				gb->F |= ZERO_FL;
				gb->PC += 1;
				cycles_used = 4;
				break;
            case 0xc0:                  // RET NZ
                if(!(gb->F & ZERO_FL))
                {
                    temp = gb_read_mem(gb, gb->SP+1) << 8;
                    temp |= gb_read_mem(gb, gb->SP);
                    gb->PC = temp;
                    gb->SP += 2;
                    cycles_used = 20;
                }
                else
                {
                    gb->PC += 1;
                    cycles_used = 8;
                }
                break;
            case 0xc1:                  // POP BC
                gb->C = gb_read_mem(gb, gb->SP);
                gb->B = gb_read_mem(gb, gb->SP + 1);
                gb->SP += 2;
                gb->PC += 1;
                cycles_used = 12;
                break;
            case 0xc2:                  // JP NZ,2bytes
                if(!(gb->F & ZERO_FL))
                {
                    gb->PC = (op2 << 8) | op1;
                    cycles_used = 16;
                }
                else
                {
                    gb->PC += 3;
                    cycles_used = 12;
                }
                break;
            case 0xc3:                  // JP 2bytes
                gb->PC = (op2 << 8) | op1;
                cycles_used = 16;
                break;
            case 0xc4:                  // CALL NZ,2bytes
                gb->PC += 3;
                if(!(gb->F & ZERO_FL))
                {
                    gb->SP -= 2;
                    gb_write_mem(gb,
                            gb->SP,
                                    gb->PC & REG_MAX);
                    gb_write_mem(gb,
                            gb->SP + 1,
                                    gb->PC >> 8);
                    gb->PC = (op2 << 8) | op1;
                    cycles_used = 24;
                }
                else
                {
                    cycles_used = 12;
                }
                break;
            case 0xc5:                  // PUSH BC
                gb->SP -= 2;
                gb->SP &= DOUBLE_REG;
                gb_write_mem(gb,
                        gb->SP,
                                gb->C);
                gb_write_mem(gb,
                        gb->SP+1,
                                gb->B);
                gb->PC += 1;
                cycles_used = 16;
                break;
            case 0xc6:                  // ADD A,1byte
                gb->F = 0;
                if(((gb->A & HALF_REG) +
                        (op1 & HALF_REG)) > HALF_REG)
                {
                    gb->F |= HC_FL;
                }
                gb->A += op1;
                if(gb->A > REG_MAX)
                {
                    gb->F |= C_FL;
                    gb->A &= REG_MAX;
                    if(gb->A == 0x00)
                    {
                        gb->F |= ZERO_FL;
                    }
                }
                gb->PC += 2;
                cycles_used = 8;
                break;
            case 0xc7:                  // RST 00H
                gb->PC += 1;
                gb->SP -= 2;
                gb_write_mem(gb,
                        gb->SP,
                                gb->PC & REG_MAX);
                gb_write_mem(gb,
                        gb->SP + 1,
                                gb->PC >> 8);
                gb->PC = 0x00;
                cycles_used = 16;
                break;
            case 0xc8:                  // RET Z
                if(gb->F & ZERO_FL)
                {
                    temp = gb_read_mem(gb, gb->SP+1) << 8;
                    temp |= gb_read_mem(gb, gb->SP);
                    gb->PC = temp;
                    gb->SP += 2;
                    cycles_used = 20;
                }
                else
                {
                    gb->PC += 1;
                    cycles_used = 8;
                }
                break;
            case 0xc9:                  // RET
                temp = gb_read_mem(gb, gb->SP+1) << 8;
                temp |= gb_read_mem(gb, gb->SP);
                gb->PC = temp;
                gb->SP += 2;
                cycles_used = 16;
                break;
            case 0xca:                  // JP Z,2bytes
                if(gb->F & ZERO_FL)
                {
                    gb->PC = (op2 << 8) | op1;
                    cycles_used = 16;
                }
                else
                {
                    gb->PC += 3;
                    cycles_used = 12;
                }
                break;
            case 0xcb:                  // PREFIX CB
                cycles_used = CB_exec(gb, op1);
                break;
            case 0xcc:                  // CALL Z,2bytes
                gb->PC += 3;
                if(gb->F & ZERO_FL)
                {
                    gb->SP -= 2;
                    gb_write_mem(gb,
                            gb->SP,
                                    gb->PC & REG_MAX);
                    gb_write_mem(gb,
                            gb->SP + 1,
                                    gb->PC >> 8);
                    gb->PC = (op2 << 8) | op1;
                    cycles_used = 24;
                }
                else
                {
                    cycles_used = 12;
                }
                break;
            case 0xcd:                  // CALL 2bytes
                gb->PC += 3;
                gb->SP -= 2;
                gb_write_mem(gb,
                        gb->SP,
                                gb->PC & REG_MAX);
                gb_write_mem(gb,
                        gb->SP + 1,
                                gb->PC >> 8);
                gb->PC = (op2 << 8) | op1;
                cycles_used = 24;
                break;
            case 0xce:                  // ADC A,1byte
                op1 += gb->F & C_FL ? 1 : 0;
                gb->F = 0;
                if(((gb->A & HALF_REG) + (op1 & HALF_REG)) >
                        HALF_REG)
                {
                    gb->F |= HC_FL;
                }
                gb->A += op1;
                if(gb->A > REG_MAX)
                {
                    gb->F |= C_FL;
                    if(gb->A == 0x100)
                    {
                        gb->F |= ZERO_FL;
                    }
                    gb->A &= REG_MAX;
                }
                gb->PC += 2;
                cycles_used = 8;
                break;
            case 0xcf:                  // RST 08H
                gb->PC += 1;
                gb->SP -= 2;
                gb_write_mem(gb,
                        gb->SP,
                                gb->PC & REG_MAX);
                gb_write_mem(gb,
                        gb->SP + 1,
                                gb->PC >> 8);
                gb->PC = 0x08;
                cycles_used = 16;
                break;
            case 0xd0:                  // RET NC
                if(!(gb->F & C_FL))
                {
                    temp = gb_read_mem(gb, gb->SP+1) << 8;
                    temp |= gb_read_mem(gb, gb->SP);
                    gb->PC = temp;
                    gb->SP += 2;
                    cycles_used = 20;
                }
                else
                {
                    gb->PC += 1;
                    cycles_used = 8;
                }
                break;
            case 0xd1:                  // POP DE
                gb->E = gb_read_mem(gb, gb->SP);
                gb->D = gb_read_mem(gb, gb->SP + 1);
                gb->SP += 2;
                gb->PC += 1;
                cycles_used = 12;
                break;
            case 0xd2:                  // JP NC,2bytes
                if(!(gb->F & C_FL))
                {
                    gb->PC = (op2 << 8) | op1;
                    cycles_used = 16;
                }
                else
                {
                    gb->PC += 3;
                    cycles_used = 12;
                }
                break;
            // No 0xd3
            case 0xd4:                  // CALL NC,2bytes
                gb->PC += 3;
                if(!(gb->F & C_FL))
                {
                    gb->SP -= 2;
                    gb_write_mem(gb,
                            gb->SP,
                                    gb->PC & REG_MAX);
                    gb_write_mem(gb,
                            gb->SP + 1,
                                    gb->PC >> 8);
                    gb->PC = (op2 << 8) | op1;
                    cycles_used = 24;
                }
                else
                {
                    cycles_used = 12;
                }
                break;
            case 0xd5:                  // PUSH DE
                gb->SP -= 2;
                gb->SP &= DOUBLE_REG;
                gb_write_mem(gb,
                        gb->SP,
                                gb->E);
                gb_write_mem(gb,
                        gb->SP+1,
                                gb->D);
                gb->PC += 1;
                cycles_used = 16;
                break;
            case 0xd6:                  // SUB 1byte
                gb->F = SUB_FL;
                if((gb->A & HALF_REG) < (op1 & HALF_REG))
                {
                    gb->F |= HC_FL;
                }
                if(gb->A <= op1)
                {
                    if(gb->A == op1)
                    {
                        gb->F |= ZERO_FL;
                    }
                    else
                    {
                        gb->F |= C_FL;
                    }
                }
                gb->A -= op1;
                gb->A &= REG_MAX;
                gb->PC += 2;
                cycles_used = 8;
                break;
            case 0xd7:                  // RST 10H
                gb->PC += 1;
                gb->SP -= 2;
                gb_write_mem(gb,
                        gb->SP,
                                gb->PC & REG_MAX);
                gb_write_mem(gb,
                        gb->SP + 1,
                                gb->PC >> 8);
                gb->PC = 0x10;
                cycles_used = 16;
                break;
            case 0xd8:                  // RET C
                if(gb->F & C_FL)
                {
                    temp = gb_read_mem(gb, gb->SP+1) << 8;
                    temp |= gb_read_mem(gb, gb->SP);
                    gb->PC = temp;
                    gb->SP += 2;
                    cycles_used = 20;
                }
                else
                {
                    gb->PC += 1;
                    cycles_used = 8;
                }
                break;
            case 0xd9:                  // RETI
                temp = gb_read_mem(gb, gb->SP+1) << 8;
                temp |= gb_read_mem(gb, gb->SP);
                gb->PC = temp;
				gb->IME = 1;
                gb->SP += 2;
                cycles_used = 16;
                break;
            case 0xda:                  // JP C,2bytes
                if(gb->F & C_FL)
                {
                    gb->PC = (op2 << 8) | op1;
                    cycles_used = 16;
                }
                else
                {
                    gb->PC += 3;
                    cycles_used = 12;
                }
                break;
            // No 0xdb
            case 0xdc:                  // CALL C,2bytes
                gb->PC += 3;
                if(gb->F & C_FL)
                {
                    gb->SP -= 2;
                    gb_write_mem(gb,
                            gb->SP,
                                    gb->PC & REG_MAX);
                    gb_write_mem(gb,
                            gb->SP + 1,
                                    gb->PC >> 8);
                    gb->PC = (op2 << 8) | op1;
                    cycles_used = 24;
                }
                else
                {
                    cycles_used = 12;
                }
                break;
            // No 0xdd
            case 0xde:                  // SBC A,1byte
                carry = 0;
                if(gb->F & C_FL)
                {
                    carry = 1;
                }
                gb->F = SUB_FL;
                if((gb->A & HALF_REG) < (op1 & HALF_REG))
                {
                    gb->F |= HC_FL;
                }
                gb->A -= carry;
                gb->A -= op1;
                if(gb->A < 0)
                {
                    gb->F |=C_FL;
                    gb->A &= REG_MAX;
                }
                gb->PC += 2;
                cycles_used = 8;
                break;
            case 0xdf:                  // RST 18H
                gb->PC += 1;
                gb->SP -= 2;
                gb_write_mem(gb,
                        gb->SP,
                                gb->PC & REG_MAX);
                gb_write_mem(gb,
                        gb->SP + 1,
                                gb->PC >> 8);
                gb->PC = 0x18;
                cycles_used = 16;
                break;
			case 0xe0:					// LD (0xff00 + 1byte),A
				gb_write_mem(gb,
						0xff00 | op1,
								gb->A);
				gb->PC += 2;
				cycles_used = 12;
				break;
			case 0xe1:					// POP HL
				gb->L = gb_read_mem(gb, gb->SP);
                gb->H = gb_read_mem(gb, gb->SP + 1);
                gb->SP += 2;
                gb->PC += 1;
                cycles_used = 12;
                break;
			case 0xe2:					// LD (0xff00 + C),A
				gb_write_mem(gb,
                    0xff00 | gb->C,
                    gb->A);
				gb->PC += 1;
				cycles_used = 8;
				break;
            // No 0xe3
            // No 0xe4
            case 0xe5:                  // PUSH HL
                gb->SP -= 2;
                gb->SP &= DOUBLE_REG;
                gb_write_mem(gb,
                        gb->SP,
                                gb->L);
                gb_write_mem(gb,
                        gb->SP+1,
                                gb->H);
                gb->PC += 1;
                cycles_used = 16;
                break;
			case 0xe6:					// AND 1byte
				gb->F = HC_FL;
				gb->A &= op1;
				if(gb->A == 0x00)
				{
					gb->F |= ZERO_FL;
				}
				gb->PC += 2;
				cycles_used = 8;
				break;
            case 0xe7:                  // RST 20H
                gb->PC += 1;
                gb->SP -= 2;
                gb_write_mem(gb,
                        gb->SP,
                                gb->PC & REG_MAX);
                gb_write_mem(gb,
                        gb->SP + 1,
                                gb->PC >> 8);
                gb->PC = 0x20;
                cycles_used = 16;
                break;
            case 0xe8:                  // ADD SP,1byte
                gb->F = 0;
                temp = op1;
                if(op1 & 0x80)
                    temp -= 256;
                if(((gb->SP & REG_MAX) + (temp & REG_MAX)) >
                        REG_MAX)
                {
                    gb->F |= HC_FL;
                }
                gb->SP += temp;
                if(gb->SP > DOUBLE_REG)
                {
                    gb->F |= C_FL;
                }
                gb->SP &= DOUBLE_REG;
                gb->PC += 2;
                cycles_used = 8;
                break;
			case 0xe9:					// JP (HL)
				gb->PC = (gb->H << 8) | gb->L;
				cycles_used = 4;
				break;
			case 0xea:					// LD (2bytes),A
				address = (op2 << 8) | op1;
				gb_write_mem(gb, address, gb->A);
				gb->PC += 3;
				cycles_used = 16;
				break;
            // No 0xeb
            // No 0xec
            // No 0xed
			case 0xee:					// XOR 1byte
				gb->F = 0;
                gb->A ^= op1;
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 2;
                cycles_used = 4;
                break;
            case 0xef:                  // RST 28H
                gb->PC += 1;
                gb->SP -= 2;
                gb_write_mem(gb,
                        gb->SP,
                                gb->PC & REG_MAX);
                gb_write_mem(gb,
                        gb->SP + 1,
                                gb->PC >> 8);
                gb->PC = 0x28;
                cycles_used = 16;
                break;
            case 0xf0:                  // LD A,(0xff00 + 1byte)
                gb->A = gb_read_mem(gb,
                        0xff00 + op1);
                gb->PC += 2;
                cycles_used = 12;
                break;
            case 0xf1:                  // POP AF
                gb->F = gb_read_mem(gb, gb->SP);
				gb->A = gb_read_mem(gb, gb->SP + 1);
                gb->SP += 2;
                gb->PC += 1;
                cycles_used = 12;
                break;
            case 0xf2:                  // LD A,(0xff00 + C)
                gb->A = gb_read_mem(gb, 0xff00 | gb->C);
                gb->PC += 1;
                cycles_used = 8;
                break;
            case 0xf3:                  // DI (disable interrupts)
				gb->IME = 0;
                gb->PC += 1;
                cycles_used = 4;
                break;
            // No 0xf4
            case 0xf5:                  // PUSH AF
                gb->SP -= 2;
                gb->SP &= DOUBLE_REG;
                gb_write_mem(gb,
                    gb->SP,
                    gb->F);
                gb_write_mem(gb,
                    gb->SP+1,
                    gb->A);
                gb->PC += 1;
                cycles_used = 16;
                break;
            case 0xf6:                  // OR 1byte
                gb->F = 0;
                gb->A |= op1;
                if(gb->A == 0x00)
                {
                    gb->F |= ZERO_FL;
                }
                gb->PC += 2;
                cycles_used = 8;
                break;
            case 0xf7:                  // RST 30H
                gb->PC += 1;
                gb->SP -= 2;
                gb_write_mem(gb,
                    gb->SP,
                    gb->PC & REG_MAX);
                gb_write_mem(gb,
                    gb->SP + 1,
                    gb->PC >> 8);
                gb->PC = 0x30;
                cycles_used = 16;
                break;
            case 0xf8:                  // LD HL,SP+1byte
                gb->F = 0;
                temp = op1;
                if(op1 & 0x80)
                    temp -= 256;
                if(((gb->SP & REG_MAX) + (temp & REG_MAX)) >
                    REG_MAX)
                {
                    gb->F |= HC_FL;
                }
                temp += gb->SP;
                if(temp > DOUBLE_REG)
                {
                    gb->F |= C_FL;
                }
                temp  &= DOUBLE_REG;
                gb->H = temp >> 8;
                gb->L = temp & REG_MAX;
                gb->PC += 2;
                cycles_used = 12;
                break;
			case 0xf9:					// LD SP,HL
				gb->SP = (gb->H << 8) | gb->L;
				gb->PC += 1;
				cycles_used = 8;
				break;
			case 0xfa:					// LD A,2bytes
				gb->A = gb_read_mem(gb,
						(op2 << 8) | op1);
				gb->PC += 3;
				cycles_used = 16;
				break;
			case 0xfb:					// EI
				gb->IME = 1;
				gb->PC += 1;
				cycles_used = 4;
				break;
            // No 0xfc
            // No 0xfd
			case 0xfe:					// CP 1byte
				gb->F = SUB_FL;
				if((gb->A & HALF_REG) < (op1 & HALF_REG))
				{
					gb->F |= HC_FL;
				}
				if(gb->A <= op1)
				{
					if(gb->A == op1)
					{
						gb->F |= ZERO_FL;
					}
					else
					{
						gb->F |= C_FL;
					}
				}
				gb->PC += 2;
				cycles_used = 8;
				break;
            case 0xff:                  // RST 38H
                gb->PC += 1;
                gb->SP -= 2;
                gb_write_mem(gb,
                        gb->SP,
                                gb->PC & REG_MAX);
                gb_write_mem(gb,
                        gb->SP + 1,
                                gb->PC >> 8);
                gb->PC = 0x38;
                cycles_used = 16;
                break;
            default:
                printf("opcode %x not implemented\n", opcode);
                exit(0);
        }

	    cycles_left -= cycles_used;

        gb->TIMA_INC -= cycles_used;
        if(gb->TIMA_INC <= 0)
        {
            if(gb->TIMA == REG_MAX)
            {
                // Request timer interrupt
                gb->IF |= 0x04;
                gb->TIMA = gb->TMA;
            }
            else
                gb->TIMA++;
            switch(gb->TAC & 0x03)     // Last 2 bits = Input Clock Sel
            {
                case 0:
                    gb->TIMA_INC = 4096;
                    break;
                case 1:
                    gb->TIMA_INC = 262144;
                    break;
                case 2:
                    gb->TIMA_INC = 65536;
                    break;
                case 3:
                    gb->TIMA_INC = 16384;
                    break;
            }
        }
		gb_check_interrupts(gb);
        // Keep gpu in sync with cpu
        // This is called after gb_check_interrupts
        //  because of the HALT instruction
		gb_gpu_update(gb, cycles_used);
    }
    return 0;
}

void gb_check_interrupts(gb_state *gb)
{
    // Check if Interrupt Master Enable is set
	if(gb->IME)
	{
        // V-Blank = 0x01
		if((gb->IE & 0x01) && (gb->IF & 0x01))
		{
			gb->IME = 0;
			gb->IF ^= 0x01;
			gb->SP -= 2;
            gb_write_mem(gb,
                gb->SP,
                gb->PC & REG_MAX);
            gb_write_mem(gb,
                gb->SP + 1,
                gb->PC >> 8);
            gb->PC = 0x40;
		}
        // LCD STAT = 0x02
		else if((gb->IE & 0x02) && (gb->IF & 0x02))
		{
			gb->IME = 0;
			gb->IF ^= 0x02;
			gb->SP -= 2;
            gb_write_mem(gb,
                gb->SP,
                gb->PC & REG_MAX);
            gb_write_mem(gb,
                gb->SP + 1,
                gb->PC >> 8);
            gb->PC = 0x48;
		}
        // Timer = 0x04
		else if((gb->IE & 0x04) && (gb->IF & 0x04))
		{
			gb->IME = 0;
			gb->IF ^= 0x04;
			gb->SP -= 2;
            gb_write_mem(gb,
                gb->SP,
                gb->PC & REG_MAX);
            gb_write_mem(gb,
                gb->SP + 1,
                gb->PC >> 8);
            gb->PC = 0x50;
		}
        // Serial = 0x08
		else if((gb->IE & 0x08) && (gb->IF & 0x08))
		{
			gb->IME = 0;
			gb->IF ^= 0x08;
			gb->SP -= 2;
            gb_write_mem(gb,
                gb->SP,
                gb->PC & REG_MAX);
            gb_write_mem(gb,
                gb->SP + 1,
                gb->PC >> 8);
            gb->PC = 0x58;
		}
        // Joypad = 0x10
		else if((gb->IE & 0x10) && (gb->IF & 0x10))
		{
			gb->IME = 0;
			gb->IF ^= 0x10;
			gb->SP -= 2;
            gb_write_mem(gb,
                gb->SP,
                gb->PC & REG_MAX);
            gb_write_mem(gb,
                gb->SP + 1,
                gb->PC >> 8);
            gb->PC = 0x60;
		}
	}
}

/*
 * 0xCB opcode instructions
 */
int CB_exec(gb_state *gb, int op1)
{
    int carry, address, temp;
    switch(op1)
    {
        case 0x00:          // RLC B
            gb->F = 0;
            carry = 0;
            if(gb->B & 0x80)
            {
                gb->F |= C_FL;
                carry = 1;
            }
            gb->B <<= 1;
            gb->B |= carry;
            gb->B &= REG_MAX;
            if(gb->B == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x01:          // RLC C
            gb->F = 0;
            carry = 0;
            if(gb->C & 0x80)
            {
                gb->F |= C_FL;
                carry = 1;
            }
            gb->C <<= 1;
            gb->C |= carry;
            gb->C &= REG_MAX;
            if(gb->C == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x02:          // RLC D
            gb->F = 0;
            carry = 0;
            if(gb->D & 0x80)
            {
                gb->F |= C_FL;
                carry = 1;
            }
            gb->D <<= 1;
            gb->D |= carry;
            gb->D &= REG_MAX;
            if(gb->D == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x03:          // RLC E
            gb->F = 0;
            carry = 0;
            if(gb->E & 0x80)
            {
                gb->F |= C_FL;
                carry = 1;
            }
            gb->E <<= 1;
            gb->E |= carry;
            gb->E &= REG_MAX;
            if(gb->E == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x04:          // RLC H
            gb->F = 0;
            carry = 0;
            if(gb->H & 0x80)
            {
                gb->F |= C_FL;
                carry = 1;
            }
            gb->H <<= 1;
            gb->H |= carry;
            gb->H &= REG_MAX;
            if(gb->H == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x05:          // RLC L
            gb->F = 0;
            carry = 0;
            if(gb->L & 0x80)
            {
                gb->F |= C_FL;
                carry = 1;
            }
            gb->L <<= 1;
            gb->L |= carry;
            gb->L &= REG_MAX;
            if(gb->L == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x06:          // RLC (HL)
            gb->F = 0;
            carry = 0;
            address = (gb->H << 8) | gb->L;
            temp = gb_read_mem(gb, address);
            if(temp & 0x80)
            {
                gb->F |= C_FL;
                carry = 1;
            }
            temp <<= 1;
            temp |= carry;
            temp &= REG_MAX;
            if(temp == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb_write_mem(gb, address, temp);
            gb->PC += 2;
            return 16;
        case 0x07:          // RLC A
            gb->F = 0;
            carry = 0;
            if(gb->A & 0x80)
            {
                gb->F |= C_FL;
                carry = 1;
            }
            gb->A <<= 1;
            gb->A |= carry;
            gb->A &= REG_MAX;
            if(gb->A == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x08:          // RRC B
            gb->F = (carry = gb->B & 0x01) << C_FL_BIT;
            gb->B >>= 1;
            gb->B |= carry << 7;
            gb->B &= REG_MAX;
            if(gb->B == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x09:          // RRC C
            gb->F = (carry = gb->C & 0x01) << C_FL_BIT;
            gb->C >>= 1;
            gb->C |= carry << 7;
            gb->C &= REG_MAX;
            if(gb->C == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x0a:          // RRC D
            gb->F = (carry = gb->D & 0x01) << C_FL_BIT;
            gb->D >>= 1;
            gb->D |= carry << 7;
            gb->D &= REG_MAX;
            if(gb->D == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x0b:          // RRC E
            gb->F = (carry = gb->E & 0x01) << C_FL_BIT;
            gb->E >>= 1;
            gb->E |= carry << 7;
            gb->E &= REG_MAX;
            if(gb->E == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x0c:          // RRC H
            gb->F = (carry = gb->H & 0x01) << C_FL_BIT;
            gb->H >>= 1;
            gb->H |= carry << 7;
            gb->H &= REG_MAX;
            if(gb->H == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x0d:          // RRC L
            gb->F = (carry = gb->L & 0x01) << C_FL_BIT;
            gb->L >>= 1;
            gb->L |= carry << 7;
            gb->L &= REG_MAX;
            if(gb->L == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x0e:          // RRC (HL)
            address = (gb->H << 8) | gb->L;
            temp = gb_read_mem(gb, address);
            gb->F = (carry = temp & 0x01) << C_FL_BIT;
            temp >>= 1;
            temp |= carry << 7;
            temp &= REG_MAX;
            if(temp == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb_write_mem(gb, address, temp);
            gb->PC += 2;
            return 16;
        case 0x0f:          // RRC A
            gb->F = (carry = gb->A & 0x01) << C_FL_BIT;
            gb->A >>= 1;
            gb->A |= carry << 7;
            gb->A &= REG_MAX;
            if(gb->A == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
		case 0x10:			// RL B
			carry = 0;
			if(gb->F & C_FL)
			{
				carry = 0x01;
			}
			gb->F = 0;
			if(gb->B & 0x80)
			{
				gb->F |= C_FL;
			}
			gb->B <<= 1;
			gb->B |= carry;
			gb->B &= REG_MAX;
			if(gb->B == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
		case 0x11:			// RL C
			carry = 0;
			if(gb->F & C_FL)
			{
				carry = 0x01;
			}
			gb->F = 0;
			if(gb->C & 0x80)
			{
				gb->F |= C_FL;
			}
			gb->C <<= 1;
			gb->C |= carry;
			gb->C &= REG_MAX;
			if(gb->C == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
		case 0x12:			// RL D
			carry = 0;
			if(gb->F & C_FL)
			{
				carry = 0x01;
			}
			gb->F = 0;
			if(gb->D & 0x80)
			{
				gb->F |= C_FL;
			}
			gb->D <<= 1;
			gb->D |= carry;
			gb->D &= REG_MAX;
			if(gb->D == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
		case 0x13:			// RL E
			carry = 0;
			if(gb->F & C_FL)
			{
				carry = 0x01;
			}
			gb->F = 0;
			if(gb->E & 0x80)
			{
				gb->F |= C_FL;
			}
			gb->E <<= 1;
			gb->E |= carry;
			gb->E &= REG_MAX;
			if(gb->E == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x14:          // RL H
            carry = 0;
			if(gb->F & C_FL)
			{
				carry = 0x01;
			}
			gb->F = 0;
			if(gb->H & 0x80)
			{
				gb->F |= C_FL;
			}
			gb->H <<= 1;
			gb->H |= carry;
			gb->H &= REG_MAX;
			if(gb->H == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x15:          // RL L
            carry = 0;
			if(gb->F & C_FL)
			{
				carry = 0x01;
			}
			gb->F = 0;
			if(gb->L & 0x80)
			{
				gb->F |= C_FL;
			}
			gb->L <<= 1;
			gb->L |= carry;
			gb->L &= REG_MAX;
			if(gb->L == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
		case 0x16:          // RL (HL)
			address = (gb->H) << 8 | gb->L;
			temp = gb_read_mem(gb, address);
			carry = 0;
			if(gb->F & C_FL)
			{
				carry = 0x01;
			}
			gb->F = 0;
			if(temp & 0x80)
			{
				gb->F |= C_FL;
			}
			temp <<= 1;
			temp |= carry;
			temp &= REG_MAX;
			if(temp == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb_write_mem(gb, address, temp);
			gb->PC += 2;
			return 16;
        case 0x17:          // RL A
            carry = 0;
			if(gb->F & C_FL)
			{
				carry = 0x01;
			}
			gb->F = 0;
			if(gb->A & 0x80)
			{
				gb->F |= C_FL;
			}
			gb->A <<= 1;
			gb->A |= carry;
			gb->A &= REG_MAX;
			if(gb->A == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x18:          // RR B
            carry = 0;
			if(gb->F & C_FL)
			{
				carry = 0x80;
			}
			gb->F = 0;
			if(gb->B & 0x01)
			{
				gb->F |= C_FL;
			}
			gb->B >>= 1;
			gb->B |= carry;
			gb->B &= REG_MAX;
			if(gb->B == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
		case 0x19:			// RR C
			carry = 0;
			if(gb->F & C_FL)
			{
				carry = 0x80;
			}
			gb->F = 0;
			if(gb->C & 0x01)
			{
				gb->F |= C_FL;
			}
			gb->C >>= 1;
			gb->C |= carry;
			gb->C &= REG_MAX;
			if(gb->C == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x1a:          // RR D
            carry = 0;
			if(gb->F & C_FL)
			{
				carry = 0x80;
			}
			gb->F = 0;
			if(gb->D & 0x01)
			{
				gb->F |= C_FL;
			}
			gb->D >>= 1;
			gb->D |= carry;
			gb->D &= REG_MAX;
			if(gb->D == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
		case 0x1b:			// RR E
			carry = 0;
			if(gb->F & C_FL)
			{
				carry = 0x80;
			}
			gb->F = 0;
			if(gb->E & 0x01)
			{
				gb->F |= C_FL;
			}
			gb->E >>= 1;
			gb->E |= carry;
			gb->E &= REG_MAX;
			if(gb->E == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x1c:          // RR H
            carry = 0;
			if(gb->F & C_FL)
			{
				carry = 0x80;
			}
			gb->F = 0;
			if(gb->H & 0x01)
			{
				gb->F |= C_FL;
			}
			gb->H >>= 1;
			gb->H |= carry;
			gb->H &= REG_MAX;
			if(gb->H == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x1d:          // RR L
            carry = 0;
			if(gb->F & C_FL)
			{
				carry = 0x80;
			}
			gb->F = 0;
			if(gb->L & 0x01)
			{
				gb->F |= C_FL;
			}
			gb->L >>= 1;
			gb->L |= carry;
			gb->L &= REG_MAX;
			if(gb->L == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x1e:          // RR (HL)
            address = (gb->H << 8) | gb->L;
            temp = gb_read_mem(gb, address);
            carry = 0;
			if(gb->F & C_FL)
			{
				carry = 0x80;
			}
			gb->F = 0;
			if(temp & 0x01)
			{
				gb->F |= C_FL;
			}
			temp >>= 1;
			temp |= carry;
			temp &= REG_MAX;
			if(temp == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb_write_mem(gb, address, temp);
			gb->PC += 2;
			return 16;
        case 0x1f:          // RR A
            carry = 0;
			if(gb->F & C_FL)
			{
				carry = 0x80;
			}
			gb->F = 0;
			if(gb->A & 0x01)
			{
				gb->F |= C_FL;
			}
			gb->A >>= 1;
			gb->A |= carry;
			gb->A &= REG_MAX;
			if(gb->A == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x20:          // SLA B
            gb->F = 0;
            if(gb->B & 0x80)
            {
                gb->F |= C_FL;
            }
            gb->B <<= 1;
            gb->B &= 0xfe;
            if(gb->B == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x21:          // SLA C
            gb->F = 0;
            if(gb->C & 0x80)
            {
                gb->F |= C_FL;
            }
            gb->C <<= 1;
            gb->C &= 0xfe;
            if(gb->C == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x22:          // SLA D
            gb->F = 0;
            if(gb->D & 0x80)
            {
                gb->F |= C_FL;
            }
            gb->D <<= 1;
            gb->D &= 0xfe;
            if(gb->D == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x23:          // SLA E
            gb->F = 0;
            if(gb->E & 0x80)
            {
                gb->F |= C_FL;
            }
            gb->E <<= 1;
            gb->E &= 0xfe;
            if(gb->E == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x24:          // SLA H
            gb->F = 0;
            if(gb->H & 0x80)
            {
                gb->F |= C_FL;
            }
            gb->H <<= 1;
            gb->H &= 0xfe;
            if(gb->H == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x25:          // SLA L
            gb->F = 0;
            if(gb->L & 0x80)
            {
                gb->F |= C_FL;
            }
            gb->L <<= 1;
            gb->L &= 0xfe;
            if(gb->L == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x26:          // SLA (HL)
            address = (gb->H << 8) | gb->L;
            temp = gb_read_mem(gb, address);
            gb->F = 0;
            if(temp & 0x80)
            {
                gb->F |= C_FL;
            }
            temp <<= 1;
            temp &= 0xfe;
            if(temp == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb_write_mem(gb, address, temp);
            gb->PC += 2;
            return 16;
		case 0x27:          // SLA A
			gb->F = 0;
			if(gb->A & 0x08)
			{
				gb->F |= C_FL;
			}
			gb->A <<= 1;
			gb->A &= 0xfe;
			if(gb->A == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x28:          // SRA B
            gb->F = 0;
			if(gb->B & 0x01)
			{
				gb->F |= C_FL;
			}
			carry = gb->B & 0x80;
			gb->B >>= 1;
			gb->B |= carry;
			gb->B &= REG_MAX;
			if(gb->B == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x29:          // SRA C
            gb->F = 0;
			if(gb->C & 0x01)
			{
				gb->F |= C_FL;
			}
			carry = gb->C & 0x80;
			gb->C >>= 1;
			gb->C |= carry;
			gb->C &= REG_MAX;
			if(gb->C == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
		case 0x2a:			// SRA D
			gb->F = 0;
			if(gb->D & 0x01)
			{
				gb->F |= C_FL;
			}
			carry = gb->D & 0x80;
			gb->D >>= 1;
			gb->D |= carry;
			gb->D &= REG_MAX;
			if(gb->D == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x2b:          // SRA E
            gb->F = 0;
			if(gb->E & 0x01)
			{
				gb->F |= C_FL;
			}
			carry = gb->E & 0x80;
			gb->E >>= 1;
			gb->E |= carry;
			gb->E &= REG_MAX;
			if(gb->E == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x2c:          // SRA H
            gb->F = 0;
			if(gb->H & 0x01)
			{
				gb->F |= C_FL;
			}
			carry = gb->H & 0x80;
			gb->H >>= 1;
			gb->H |= carry;
			gb->H &= REG_MAX;
			if(gb->H == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x2d:          // SRA L
            gb->F = 0;
			if(gb->L & 0x01)
			{
				gb->F |= C_FL;
			}
			carry = gb->L & 0x80;
			gb->L >>= 1;
			gb->L |= carry;
			gb->L &= REG_MAX;
			if(gb->L == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x2e:          // SRA (HL)
            address = (gb->H << 8) | gb->L;
            temp = gb_read_mem(gb, address);
            gb->F = 0;
			if(temp & 0x01)
			{
				gb->F |= C_FL;
			}
			carry = temp & 0x80;
			temp >>= 1;
			temp |= carry;
			temp &= REG_MAX;
			if(temp == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 16;
		case 0x2f:          // SRA A
			gb->F = 0;
			if(gb->A & 0x01)
			{
				gb->F |= C_FL;
			}
			carry = gb->A & 0x80;
			gb->A >>= 1;
			gb->A |= carry;
			gb->A &= REG_MAX;
			if(gb->A == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x30:          // SWAP B
            gb->F = 0;
            if(gb->B == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->B = ((gb->B & HALF_REG) << 4) |
                ((gb->B & 0xf0) >> 4);
            gb->PC += 2;
            return 8;
        case 0x31:          // SWAP C
            gb->F = 0;
            if(gb->C == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->C = ((gb->C & HALF_REG) << 4) |
                ((gb->C & 0xf0) >> 4);
            gb->PC += 2;
            return 8;
        case 0x32:          // SWAP D
            gb->F = 0;
            if(gb->D == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->D = ((gb->D & HALF_REG) << 4) |
                ((gb->D & 0xf0) >> 4);
            gb->PC += 2;
            return 8;
        case 0x33:          // SWAP E
            gb->F = 0;
            if(gb->E == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->E = ((gb->E & HALF_REG) << 4) |
                ((gb->E & 0xf0) >> 4);
            gb->PC += 2;
            return 8;
        case 0x34:          // SWAP H
            gb->F = 0;
            if(gb->H == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->H = ((gb->H & HALF_REG) << 4) |
                ((gb->H & 0xf0) >> 4);
            gb->PC += 2;
            return 8;
        case 0x35:          // SWAP L
            gb->F = 0;
            if(gb->L == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->L = ((gb->L & HALF_REG) << 4) |
                ((gb->L & 0xf0) >> 4);
            gb->PC += 2;
            return 8;
        case 0x36:          // SWAP (HL)
            gb->F = 0;
            address = (gb->H << 8) | gb->L;
            temp = gb_read_mem(gb, address);
            if(temp == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            temp = ((temp & HALF_REG) << 4) |
                ((temp & 0xf0) >> 4);
            gb_write_mem(gb, address, temp);
            gb->PC += 2;
            return 16;
        case 0x37:          // SWAP A
            gb->F = 0;
            if(gb->A == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->A = ((gb->A & HALF_REG) << 4) |
                ((gb->A & 0xf0) >> 4);
            gb->PC += 2;
            return 8;
		case 0x38:          // SRL B
			gb->F = 0;
			if(gb->B & 0x01)
			{
				gb->F |= C_FL;
			}
			gb->B >>= 1;
			gb->B &= REG_MAX;
			if(gb->B == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x39:          // SRL C
            gb->F = 0;
			if(gb->C & 0x01)
			{
				gb->F |= C_FL;
			}
			gb->C >>= 1;
			gb->C &= REG_MAX;
			if(gb->C == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x3a:          // SRL D
            gb->F = 0;
			if(gb->D & 0x01)
			{
				gb->F |= C_FL;
			}
			gb->D >>= 1;
			gb->D &= REG_MAX;
			if(gb->D == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x3b:          // SRL E
            gb->F = 0;
			if(gb->E & 0x01)
			{
				gb->F |= C_FL;
			}
			gb->E >>= 1;
			gb->E &= REG_MAX;
			if(gb->E == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x3c:          // SRL H
            gb->F = 0;
			if(gb->H & 0x01)
			{
				gb->F |= C_FL;
			}
			gb->H >>= 1;
			gb->H &= REG_MAX;
			if(gb->H == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x3d:          // SRL L
            gb->F = 0;
			if(gb->L & 0x01)
			{
				gb->F |= C_FL;
			}
			gb->L >>= 1;
			gb->L &= REG_MAX;
			if(gb->L == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x3e:          // SRL (HL)
            gb->F = 0;
            address = (gb->H << 8) | gb->L;
            temp = gb_read_mem(gb, address);
			if(temp & 0x01)
			{
				gb->F |= C_FL;
			}
			temp >>= 1;
			temp &= REG_MAX;
			if(temp == 0x00)
			{
				gb->F |= ZERO_FL;
			}
			gb_write_mem(gb, address, temp);
			gb->PC += 2;
			return 16;
        case 0x3f:          // SRL A
            gb->F = 0;
            if(gb->A & 0x01)
            {
                gb->F |= C_FL;
            }
            gb->A >>= 1;
            gb->A &= REG_MAX;
            if(gb->A == 0x00)
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x40:          // BIT 0,B
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->B & 0x01))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x41:          // BIT 0,C
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->C & 0x01))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x42:          // BIT 0,D
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->D & 0x01))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
		case 0x43:			// BIT 0,E
			gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->E & 0x01))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x44:          // BIT 0,H
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->H & 0x01))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x45:          // BIT 0,L
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->L & 0x01))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x46:          // BIT 0,(HL)
            gb->F &= C_FL;
            gb->F |= HC_FL;
            temp = gb_read_mem(gb, (gb->H << 8) | gb->L);
            if(!(temp & 0x01))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 16;
		case 0x47:          // BIT 0,A
			gb->F &= C_FL;
			gb->F |= HC_FL;
			if(!(gb->A & 0x01))
			{
				gb->F |= ZERO_FL;
			}
			gb->PC += 2;
			return 8;
        case 0x48:          // BIT 1,B
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->B & 0x02))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x49:          // BIT 1,C
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->C & 0x02))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x4a:          // BIT 1,D
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->D & 0x02))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x4b:          // BIT 1,E
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->E & 0x02))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x4c:          // BIT 1,H
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->H & 0x02))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x4d:          // BIT 1,L
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->L & 0x02))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x4e:          // BIT 1,(HL)
            gb->F &= C_FL;
            gb->F |= HC_FL;
            temp = gb_read_mem(gb, (gb->H << 8) | gb->L);
            if(!(temp & 0x02))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 16;
        case 0x4f:          // BIT 1,A
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->A & 0x02))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
		case 0x50:			// BIT 2,B
			gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->B & 0x04))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x51:          // BIT 2,C
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->C & 0x04))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x52:          // BIT 2,D
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->D & 0x04))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x53:          // BIT 2,E
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->E & 0x04))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x54:          // BIT 2,H
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->H & 0x04))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x55:          // BIT 2,L
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->L & 0x04))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x56:          // BIT 2,(HL)
            gb->F &= C_FL;
            gb->F |= HC_FL;
            temp = gb_read_mem(gb, (gb->H << 8) | gb->L);
            if(!(temp & 0x04))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 16;
        case 0x57:          // BIT 2,A
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->A & 0x04))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x58:          // BIT 3,B
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->B & 0x08))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x59:          // BIT 3,C
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->C & 0x08))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x5a:          // BIT 3,D
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->D & 0x08))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x5b:          // BIT 3,E
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->E & 0x08))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x5c:          // BIT 3,H
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->H & 0x08))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x5d:          // BIT 3,L
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->L & 0x08))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x5e:          // BIT 3,(HL)
            gb->F &= C_FL;
            gb->F |= HC_FL;
            temp = gb_read_mem(gb, (gb->H << 8) | gb->L);
            if(!(temp & 0x08))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 16;
		case 0x5f:			// BIT 3,A
			gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->A & 0x08))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
		case 0x60:			// BIT 4,B
			gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->B & 0x10))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x61:          // BIT 4,C
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->C & 0x10))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x62:          // BIT 4,D
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->D & 0x10))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x63:          // BIT 4,E
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->E & 0x10))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x64:          // BIT 4,H
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->H & 0x10))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x65:          // BIT 4,L
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->L & 0x10))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x66:          // BIT 4,(HL)
            gb->F &= C_FL;
            gb->F |= HC_FL;
            temp = gb_read_mem(gb, (gb->H << 8) | gb->L);
            if(!(temp & 0x10))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 16;
		case 0x67:			// BIT 4,A
			gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->A & 0x10))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
		case 0x68:			// BIT 5,B
			gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->B & 0x20))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x69:          // BIT 5,C
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->C & 0x20))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x6a:          // BIT 5,D
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->D & 0x20))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x6b:          // BIT 5,E
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->E & 0x20))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x6c:          // BIT 5,H
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->H & 0x20))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x6d:          // BIT 5,L
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->L & 0x20))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x6e:          // BIT 5,(HL)
            gb->F &= C_FL;
            gb->F |= HC_FL;
            temp = gb_read_mem(gb, (gb->H << 8) | gb->L);
            if(!(temp & 0x20))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 16;
		case 0x6f:			// BIT 5,A
			gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->A & 0x20))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
		case 0x70:			// BIT 6,B
			gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->B & 0x40))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x71:          // BIT 6,C
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->C & 0x40))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x72:          // BIT 6,D
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->D & 0x40))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x73:          // BIT 6,E
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->E & 0x40))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x74:          // BIT 6,H
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->H & 0x40))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x75:          // BIT 6,L
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->L & 0x40))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x76:          // BIT 6,(HL)
            gb->F &= C_FL;
            gb->F |= HC_FL;
            temp = gb_read_mem(gb, (gb->H << 8) | gb->L);
            if(!(temp & 0x40))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 16;
		case 0x77:			// BIT 6,A
			gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->A & 0x40))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
		case 0x78:			// BIT 7,B
			gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->B & 0x80))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x79:          // BIT 7,C
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->C & 0x80))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
		case 0x7a:			// BIT 7,D
			gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->D & 0x80))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x7b:          // BIT 7,E
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->E & 0x80))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x7c:          // BIT 7,H
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->H & 0x80))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x7d:          // BIT 7,L
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->L & 0x80))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x7e:          // BIT 7,(HL)
            gb->F &= C_FL;
            gb->F |= HC_FL;
            temp = gb_read_mem(gb, (gb->H << 8) | gb->L);
            if(!(temp & 0x80))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 16;
        case 0x7f:          // BIT 7,A
            gb->F &= C_FL;
            gb->F |= HC_FL;
            if(!(gb->A & 0x80))
            {
                gb->F |= ZERO_FL;
            }
            gb->PC += 2;
            return 8;
        case 0x80:          // RES 0,B
            gb->B &= 0xfe;
            gb->PC += 2;
            return 8;
        case 0x81:          // RES 0,C
            gb->C &= 0xfe;
            gb->PC += 2;
            return 8;
        case 0x82:          // RES 0,D
            gb->D &= 0xfe;
            gb->PC += 2;
            return 8;
        case 0x83:          // RES 0,E
            gb->E &= 0xfe;
            gb->PC += 2;
            return 8;
        case 0x84:          // RES 0,H
            gb->H &= 0xfe;
            gb->PC += 2;
            return 8;
        case 0x85:          // RES 0,L
            gb->L &= 0xfe;
            gb->PC += 2;
            return 8;
        case 0x86:          // RES 0,(HL)
            address = (gb->H << 8) | gb->L;
            temp = gb_read_mem(gb, address);
            temp &= 0xfe;
            gb_write_mem(gb, address, temp);
            gb->PC += 2;
            return 16;
        case 0x87:          // RES 0,A
            gb->A &= 0xfe;
            gb->PC += 2;
            return 8;
        case 0x88:          // RES 1,B
            gb->B &= 0xfd;
            gb->PC += 2;
            return 8;
        case 0x89:          // RES 1,C
            gb->C &= 0xfd;
            gb->PC += 2;
            return 8;
        case 0x8a:          // RES 1,D
            gb->D &= 0xfd;
            gb->PC += 2;
            return 8;
        case 0x8b:          // RES 1,E
            gb->E &= 0xfd;
            gb->PC += 2;
            return 8;
        case 0x8c:          // RES 1,H
            gb->H &= 0xfd;
            gb->PC += 2;
            return 8;
        case 0x8d:          // RES 1,L
            gb->L &= 0xfd;
            gb->PC += 2;
            return 8;
        case 0x8e:          // RES 1,(HL)
            address = (gb->H << 8) | gb->L;
            temp = gb_read_mem(gb, address);
            temp &= 0xfd;
            gb_write_mem(gb, address, temp);
            gb->PC += 2;
            return 16;
        case 0x8f:          // RES 1,A
            gb->A &= 0xfd;
            gb->PC += 2;
            return 8;
        case 0x90:          // RES 2,B
            gb->B &= 0xfb;
            gb->PC += 2;
            return 8;
        case 0x91:          // RES 2,C
            gb->C &= 0xfb;
            gb->PC += 2;
            return 8;
        case 0x92:          // RES 2,D
            gb->D &= 0xfb;
            gb->PC += 2;
            return 8;
        case 0x93:          // RES 2,E
            gb->E &= 0xfb;
            gb->PC += 2;
            return 8;
        case 0x94:          // RES 2,H
            gb->H &= 0xfb;
            gb->PC += 2;
            return 8;
        case 0x95:          // RES 2,L
            gb->L &= 0xfb;
            gb->PC += 2;
            return 8;
        case 0x96:          // RES 2,(HL)
            address = (gb->H << 8) | gb->L;
            temp = gb_read_mem(gb, address);
            temp &= 0xfb;
            gb_write_mem(gb, address, temp);
            gb->PC += 2;
            return 16;
        case 0x97:          // RES 2,A
            gb->A &= 0xfb;
            gb->PC += 2;
            return 8;
        case 0x98:          // RES 3,B
            gb->B &= 0xf7;
            gb->PC += 2;
            return 8;
        case 0x99:          // RES 3,C
            gb->C &= 0xf7;
            gb->PC += 2;
            return 8;
        case 0x9a:          // RES 3,D
            gb->D &= 0xf7;
            gb->PC += 2;
            return 8;
        case 0x9b:          // RES 3,E
            gb->E &= 0xf7;
            gb->PC += 2;
            return 8;
        case 0x9c:          // RES 3,H
            gb->H &= 0xf7;
            gb->PC += 2;
            return 8;
        case 0x9d:          // RES 3,L
            gb->L &= 0xf7;
            gb->PC += 2;
            return 8;
        case 0x9e:          // RES 3,(HL)
            address = (gb->H << 8) | gb->L;
            temp = gb_read_mem(gb, address);
            temp &= 0xf7;
            gb_write_mem(gb, address, temp);
            gb->PC += 2;
            return 16;
        case 0x9f:          // RES 3,A
            gb->A &= 0xf7;
            gb->PC += 2;
            return 8;
        case 0xa0:          // RES 4,B
            gb->B &= 0xef;
            gb->PC += 2;
            return 8;
        case 0xa1:          // RES 4,C
            gb->C &= 0xef;
            gb->PC += 2;
            return 8;
        case 0xa2:          // RES 4,D
            gb->D &= 0xef;
            gb->PC += 2;
            return 8;
        case 0xa3:          // RES 4,E
            gb->E &= 0xef;
            gb->PC += 2;
            return 8;
        case 0xa4:          // RES 4,H
            gb->H &= 0xef;
            gb->PC += 2;
            return 8;
        case 0xa5:          // RES 4,L
            gb->L &= 0xef;
            gb->PC += 2;
            return 8;
        case 0xa6:          // RES 4,(HL)
            address = (gb->H << 8) | gb->L;
            temp = gb_read_mem(gb, address);
            temp &= 0xef;
            gb_write_mem(gb, address, temp);
            gb->PC += 2;
            return 16;
        case 0xa7:          // RES 4,A
            gb->A &= 0xef;
            gb->PC += 2;
            return 8;
        case 0xa8:          // RES 5,B
            gb->B &= 0xdf;
            gb->PC += 2;
            return 8;
        case 0xa9:          // RES 5,C
            gb->C &= 0xdf;
            gb->PC += 2;
            return 8;
        case 0xaa:          // RES 5,D
            gb->D &= 0xdf;
            gb->PC += 2;
            return 8;
        case 0xab:          // RES 5,E
            gb->E &= 0xdf;
            gb->PC += 2;
            return 8;
        case 0xac:          // RES 5,H
            gb->H &= 0xdf;
            gb->PC += 2;
            return 8;
        case 0xad:          // RES 5,L
            gb->L &= 0xdf;
            gb->PC += 2;
            return 8;
        case 0xae:          // RES 5,(HL)
            address = (gb->H << 8) | gb->L;
            temp = gb_read_mem(gb, address);
            temp &= 0xdf;
            gb_write_mem(gb, address, temp);
            gb->PC += 2;
            return 16;
        case 0xaf:          // RES 5,A
            gb->A &= 0xdf;
            gb->PC += 2;
            return 8;
        case 0xb0:          // RES 6,B
            gb->B &= 0xbf;
            gb->PC += 2;
            return 8;
        case 0xb1:          // RES 6,C
            gb->C &= 0xbf;
            gb->PC += 2;
            return 8;
        case 0xb2:          // RES 6,D
            gb->D &= 0xbf;
            gb->PC += 2;
            return 8;
        case 0xb3:          // RES 6,E
            gb->E &= 0xbf;
            gb->PC += 2;
            return 8;
        case 0xb4:          // RES 6,H
            gb->H &= 0xbf;
            gb->PC += 2;
            return 8;
        case 0xb5:          // RES 6,L
            gb->L &= 0xbf;
            gb->PC += 2;
            return 8;
        case 0xb6:          // RES 6,(HL)
            address = (gb->H << 8) | gb->L;
            temp = gb_read_mem(gb, address);
            temp &= 0xbf;
            gb_write_mem(gb, address, temp);
            gb->PC += 2;
            return 16;
        case 0xb7:          // RES 6,A
            gb->A &= 0xbf;
            gb->PC += 2;
            return 8;
        case 0xb8:          // RES 7,B
            gb->B &= 0x7f;
            gb->PC += 2;
            return 8;
        case 0xb9:          // RES 7,C
            gb->C &= 0x7f;
            gb->PC += 2;
            return 8;
        case 0xba:          // RES 7,D
            gb->D &= 0x7f;
            gb->PC += 2;
            return 8;
        case 0xbb:          // RES 7,E
            gb->E &= 0x7f;
            gb->PC += 2;
            return 8;
        case 0xbc:          // RES 7,H
            gb->H &= 0x7f;
            gb->PC += 2;
            return 8;
        case 0xbd:          // RES 7,L
            gb->L &= 0x7f;
            gb->PC += 2;
            return 8;
        case 0xbe:          // RES 7,(HL)
            address = (gb->H << 8) | gb->L;
            temp = gb_read_mem(gb, address);
            temp &= 0x7f;
            gb_write_mem(gb, address, temp);
            gb->PC += 2;
            return 16;
        case 0xbf:          // RES 7,A
            gb->A &= 0x7f;
            gb->PC += 2;
            return 8;
        case 0xc0:          // SET 0,B
            gb->B |= 0x01;
			gb->PC += 2;
			return 8;
        case 0xc1:          // SET 0,C
            gb->C |= 0x01;
			gb->PC += 2;
			return 8;
        case 0xc2:          // SET 0,D
            gb->D |= 0x01;
			gb->PC += 2;
			return 8;
        case 0xc3:          // SET 0,E
            gb->E |= 0x01;
			gb->PC += 2;
			return 8;
        case 0xc4:          // SET 0,H
            gb->H |= 0x01;
			gb->PC += 2;
			return 8;
        case 0xc5:          // SET 0,L
            gb->L |= 0x01;
			gb->PC += 2;
			return 8;
        case 0xc6:          // SET 0,(HL)
            address = (gb->H << 8) | gb->L;
			temp = gb_read_mem(gb, address);
			temp |= 0x01;
			gb_write_mem(gb, address, temp);
			gb->PC += 2;
			return 16;
        case 0xc7:          // SET 0,A
            gb->A |= 0x01;
			gb->PC += 2;
			return 8;
        case 0xc8:          // SET 1,B
            gb->B |= 0x02;
			gb->PC += 2;
			return 8;
        case 0xc9:          // SET 1,C
            gb->C |= 0x02;
			gb->PC += 2;
			return 8;
        case 0xca:          // SET 1,D
            gb->D |= 0x02;
			gb->PC += 2;
			return 8;
        case 0xcb:          // SET 1,E
            gb->E |= 0x02;
			gb->PC += 2;
			return 8;
        case 0xcc:          // SET 1,H
            gb->H |= 0x02;
			gb->PC += 2;
			return 8;
        case 0xcd:          // SET 1,L
            gb->L |= 0x02;
			gb->PC += 2;
			return 8;
        case 0xce:          // SET 1,(HL)
            address = (gb->H << 8) | gb->L;
			temp = gb_read_mem(gb, address);
			temp |= 0x02;
			gb_write_mem(gb, address, temp);
			gb->PC += 2;
			return 16;
        case 0xcf:          // SET 1,A
            gb->A |= 0x02;
			gb->PC += 2;
			return 8;
        case 0xd0:          // SET 2,B
            gb->B |= 0x04;
			gb->PC += 2;
			return 8;
        case 0xd1:          // SET 2,C
            gb->C |= 0x04;
			gb->PC += 2;
			return 8;
        case 0xd2:          // SET 2,D
            gb->D |= 0x04;
			gb->PC += 2;
			return 8;
        case 0xd3:          // SET 2,E
            gb->E |= 0x04;
			gb->PC += 2;
			return 8;
        case 0xd4:          // SET 2,H
            gb->H |= 0x04;
			gb->PC += 2;
			return 8;
        case 0xd5:          // SET 2,L
            gb->L |= 0x04;
			gb->PC += 2;
			return 8;
        case 0xd6:          // SET 2,(HL)
            address = (gb->H << 8) | gb->L;
			temp = gb_read_mem(gb, address);
			temp |= 0x04;
			gb_write_mem(gb, address, temp);
			gb->PC += 2;
			return 16;
        case 0xd7:          // SET 2,A
            gb->A |= 0x04;
			gb->PC += 2;
			return 8;
        case 0xd8:          // SET 3,B
            gb->B |= 0x08;
			gb->PC += 2;
			return 8;
        case 0xd9:          // SET 3,C
            gb->C |= 0x08;
			gb->PC += 2;
			return 8;
        case 0xda:          // SET 3,D
            gb->D |= 0x08;
			gb->PC += 2;
			return 8;
        case 0xdb:          // SET 3,E
            gb->E |= 0x08;
			gb->PC += 2;
			return 8;
        case 0xdc:          // SET 3,H
            gb->H |= 0x08;
			gb->PC += 2;
			return 8;
        case 0xdd:          // SET 3,L
            gb->L |= 0x08;
			gb->PC += 2;
			return 8;
        case 0xde:          // SET 3,(HL)
            address = (gb->H << 8) | gb->L;
			temp = gb_read_mem(gb, address);
			temp |= 0x08;
			gb_write_mem(gb, address, temp);
			gb->PC += 2;
			return 16;
        case 0xdf:          // SET 3,A
            gb->A |= 0x08;
			gb->PC += 2;
			return 8;
        case 0xe0:          // SET 4,B
            gb->B |= 0x10;
			gb->PC += 2;
			return 8;
        case 0xe1:          // SET 4,C
            gb->C |= 0x10;
			gb->PC += 2;
			return 8;
        case 0xe2:          // SET 4,D
            gb->D |= 0x10;
			gb->PC += 2;
			return 8;
        case 0xe3:          // SET 4,E
            gb->E |= 0x10;
			gb->PC += 2;
			return 8;
        case 0xe4:          // SET 4,H
            gb->H |= 0x10;
			gb->PC += 2;
			return 8;
        case 0xe5:          // SET 4,L
            gb->L |= 0x10;
			gb->PC += 2;
			return 8;
        case 0xe6:          // SET 4,(HL)
            address = (gb->H << 8) | gb->L;
			temp = gb_read_mem(gb, address);
			temp |= 0x10;
			gb_write_mem(gb, address, temp);
			gb->PC += 2;
			return 16;
        case 0xe7:          // SET 4,A
            gb->A |= 0x10;
			gb->PC += 2;
			return 8;
        case 0xe8:          // SET 5,B
            gb->B |= 0x20;
			gb->PC += 2;
			return 8;
        case 0xe9:          // SET 5,C
            gb->C |= 0x20;
			gb->PC += 2;
			return 8;
        case 0xea:          // SET 5,D
            gb->D |= 0x20;
			gb->PC += 2;
			return 8;
        case 0xeb:          // SET 5,E
            gb->E |= 0x20;
			gb->PC += 2;
			return 8;
        case 0xec:          // SET 5,H
            gb->H |= 0x20;
			gb->PC += 2;
			return 8;
        case 0xed:          // SET 5,L
            gb->L |= 0x20;
			gb->PC += 2;
			return 8;
        case 0xee:          // SET 5,(HL)
            address = (gb->H << 8) | gb->L;
			temp = gb_read_mem(gb, address);
			temp |= 0x20;
			gb_write_mem(gb, address, temp);
			gb->PC += 2;
			return 16;
        case 0xef:          // SET 5,A
            gb->A |= 0x20;
			gb->PC += 2;
			return 8;
        case 0xf0:          // SET 6,B
            gb->B |= 0x40;
			gb->PC += 2;
			return 8;
        case 0xf1:          // SET 6,C
            gb->C |= 0x40;
			gb->PC += 2;
			return 8;
        case 0xf2:          // SET 6,D
            gb->D |= 0x40;
			gb->PC += 2;
			return 8;
        case 0xf3:          // SET 6,E
            gb->E |= 0x40;
			gb->PC += 2;
			return 8;
        case 0xf4:          // SET 6,H
            gb->H |= 0x40;
			gb->PC += 2;
			return 8;
        case 0xf5:          // SET 6,L
            gb->L |= 0x40;
			gb->PC += 2;
			return 8;
        case 0xf6:          // SET 6,(HL)
            address = (gb->H << 8) | gb->L;
			temp = gb_read_mem(gb, address);
			temp |= 0x40;
			gb_write_mem(gb, address, temp);
			gb->PC += 2;
			return 16;
        case 0xf7:          // SET 6,A
            gb->A |= 0x40;
			gb->PC += 2;
			return 8;
        case 0xf8:          // SET 7,B
            gb->B |= 0x80;
			gb->PC += 2;
			return 8;
        case 0xf9:          // SET 7,C
            gb->C |= 0x80;
			gb->PC += 2;
			return 8;
        case 0xfa:          // SET 7,D
            gb->D |= 0x80;
			gb->PC += 2;
			return 8;
        case 0xfb:          // SET 7,E
            gb->E |= 0x80;
			gb->PC += 2;
			return 8;
        case 0xfc:          // SET 7,H
            gb->H |= 0x80;
			gb->PC += 2;
			return 8;
        case 0xfd:          // SET 7,L
            gb->L |= 0x80;
			gb->PC += 2;
			return 8;
		case 0xfe:			// SET 7,(HL)
			address = (gb->H << 8) | gb->L;
			temp = gb_read_mem(gb, address);
			temp |= 0x80;
			gb_write_mem(gb, address, temp);
			gb->PC += 2;
			return 16;
		case 0xff:          // SET 7, A
			gb->A |= 0x80;
			gb->PC += 2;
			return 8;
    }
}

/*
 * This function sets gameboy state
 * to default values
 */
void gb_reset_cpu(gb_state *gb)
{
    gb->A = 0x01;
    gb->F = 0xb0;
    gb->B = 0x00;
    gb->C = 0x13;
    gb->D = 0x00;
    gb->E = 0xd8;
    gb->H = 0x01;
    gb->L = 0x4d;
    gb->SP = 0xfffe;
    gb->TIMA = 0x00;
    gb->TMA = 0x00;
    gb->TAC = 0x00;
    gb->gpu_state.LCDC = 0x91;
    gb->gpu_state.SCY = 0x00;
    gb->gpu_state.SCX = 0x00;
    gb->gpu_state.LYC = 0x00;
    gb->gpu_state.BGP = 0xfc;
    gb->gpu_state.OBP0 = 0xff;
    gb->gpu_state.OBP1 = 0xff;
	gb->gpu_state.WX = 0x00;
    gb->gpu_state.WY = 0x00;
	gb->IE = 0x00;
    gb->gpu_state.cycles = 0x00;
	gb->PC = 0x100;
	gb->P1 = 0xff;
	gb->gpu_state.LY = 0x00;

    // Start at ROM1
	gb->rom_offset = 1024 * 16;
	gb->mbc.reg1 = 0x01;
	gb->mbc.reg3 = 0x00;

	gb->eram = 0;
	gb->eram_offset = 0x00;
	// TODO: handle MBC RTC values here

    gb->gpu_state.fps = DEFAULT_FPS;
    // If bit 7 is set at address 0x143, the
    //  game uses gameboy color functions
    if(gb_read_mem(gb, 0x143) & 0x80)
    {
        gb->mode = GBC;
        gb->cpu_freq = GBC_FREQ;
    }
    else
    {
        gb->mode = GB;
        gb->cpu_freq = GB_FREQ;
    }
    return;
}

/*
 * This function allocates memory to hold
 * the gameboy's state. Memory is not
 * initialized on purpose (except oam)
 */
void gb_init(gb_state *gb, char *fileName)
{
    gb->eram_size = 0;
    struct stat st;
    FILE *gb_rom = fopen(fileName, "rb");
    if (stat(fileName, &st) != 0)
    {
        fprintf(stderr, "File stat failed\n");
		exit(2);
    }

    gb->rom  = (unsigned char *)malloc(st.st_size);
    gb->vram = (unsigned char *)malloc(VRAM_SIZE);
    gb->wram = (unsigned char *)malloc(WRAM_SIZE);
    gb->hram = (unsigned char *)malloc(HRAM_SIZE);
    gb->oam  = (unsigned char *)malloc(OAM_SIZE);

    if(!(gb->rom && gb->vram && gb->eram &&
         gb->wram && gb->hram && gb->oam))
    {
        fprintf(stderr, "Not enough memory\n");
        exit(1);
    }

    memset(gb->oam, 0, OAM_SIZE);

    fread(gb->rom, sizeof(char), st.st_size, gb_rom);
    fclose(gb_rom);

    gb_reset_cpu(gb);

    // Check for external hardware
    gb->ext = gb_read_mem(gb, 0x147);
    // Address 0x149 specifies the size
    //  of external RAM
    switch(gb_read_mem(gb, 0x149))
    {
        case 0x00:
            // MBC2 requires value 0x00 at address 0x149
            //  and always includes 512 bytes of RAM
            if(gb->ext == MBC2 ||
               gb->ext == MBC2_BATT)
            {
                gb->eram_size = 512;
            }
            break;
        case 0x01:
            gb->eram_size = 1024*2;
            break;
        case 0x02:
            gb->eram_size = 1024*8;
            break;
        case 0x03:
            gb->eram_size = 1024*32;
            break;
    }

    if(gb->eram_size != 0)
    {
        gb->eram = (unsigned char *)malloc(gb->eram_size);
        if(!gb->eram)
        {
            fprintf(stderr, "Not enough memory\n");
            exit(1);
        }
        // Load saved data, if it exists
        FILE * ramSave = 0;
        // Add 5 chars for ".sav" (four chars plus null terminator)
        char * saveName =
                malloc(sizeof(char)*strlen(fileName)+5);
        strcpy(saveName, fileName);
        strcat(saveName, ".sav");
        ramSave = fopen(saveName, "rb");
        if(ramSave)
        {
            // It is okay if this read fails
            fread(gb->eram, 1, gb->eram_size, ramSave);
            fclose(ramSave);
        }
        free(saveName);
    }

    return;
}
